Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
sunho committed Jun 7, 2021
1 parent 4d9715d commit 84faa38
Show file tree
Hide file tree
Showing 48 changed files with 3,500 additions and 98 deletions.
47 changes: 47 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
BasedOnStyle: Google
AccessModifierOffset: -2
ConstructorInitializerIndentWidth: 4
AlignEscapedNewlinesLeft: false
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
AllowShortLoopsOnASingleLine: false
AlwaysBreakTemplateDeclarations: true
AlwaysBreakBeforeMultilineStrings: false
BreakBeforeBinaryOperators: false
BreakBeforeTernaryOperators: false
BreakConstructorInitializersBeforeComma: true
BinPackParameters: true
ColumnLimit: 100
ConstructorInitializerAllOnOneLineOrOnePerLine: true
DerivePointerBinding: true
ExperimentalAutoDetectBinPacking: false
IndentCaseLabels: true
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCSpaceBeforeProtocolList: true
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 60
PenaltyBreakString: 1
PenaltyBreakFirstLessLess: 1000
PenaltyExcessCharacter: 1000
PenaltyReturnTypeOnItsOwnLine: 90
PointerBindsToType: false
SpacesBeforeTrailingComments: 2
Cpp11BracedListStyle: false
Standard: Auto
IndentWidth: 4
TabWidth: 2
UseTab: Never
BreakBeforeBraces: Custom
IndentFunctionDeclarationAfterType: false
SpacesInParentheses: false
SpacesInAngles: false
SpaceInEmptyParentheses: false
SpacesInCStyleCastParentheses: false
SpaceAfterControlStatementKeyword: true
SpaceBeforeAssignmentOperators: true
ContinuationIndentWidth: 4
233 changes: 233 additions & 0 deletions .github/workflows/cli.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
name: CMake Build Matrix

on: [push]

jobs:
build:
name: ${{ matrix.config.name }}
runs-on: ${{ matrix.config.os }}
strategy:
fail-fast: false
matrix:
config:
- {
name: "Windows Latest MSVC", artifact: "Windows-MSVC.tar.xz",
os: windows-latest,
build_type: "Release", cc: "cl", cxx: "cl",
environment_script: "C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/VC/Auxiliary/Build/vcvars64.bat"
}
- {
name: "Windows Latest MinGW", artifact: "Windows-MinGW.tar.xz",
os: windows-latest,
build_type: "Release", cc: "gcc", cxx: "g++"
}
- {
name: "Ubuntu Latest GCC", artifact: "Linux.tar.xz",
os: ubuntu-latest,
build_type: "Release", cc: "gcc", cxx: "g++"
}
- {
name: "macOS Latest Clang", artifact: "macOS.tar.xz",
os: macos-latest,
build_type: "Release", cc: "clang", cxx: "clang++"
}

steps:
- name: Checkout repository
uses: actions/checkout@v2
with:
submodules: 'true'

- name: Download Ninja and CMake
id: cmake_and_ninja
shell: cmake -P {0}
run: |
set(ninja_version "1.9.0")
set(cmake_version "3.16.2")
message(STATUS "Using host CMake version: ${CMAKE_VERSION}")
if ("${{ runner.os }}" STREQUAL "Windows")
set(ninja_suffix "win.zip")
set(cmake_suffix "win64-x64.zip")
set(cmake_dir "cmake-${cmake_version}-win64-x64/bin")
elseif ("${{ runner.os }}" STREQUAL "Linux")
set(ninja_suffix "linux.zip")
set(cmake_suffix "Linux-x86_64.tar.gz")
set(cmake_dir "cmake-${cmake_version}-Linux-x86_64/bin")
elseif ("${{ runner.os }}" STREQUAL "macOS")
set(ninja_suffix "mac.zip")
set(cmake_suffix "Darwin-x86_64.tar.gz")
set(cmake_dir "cmake-${cmake_version}-Darwin-x86_64/CMake.app/Contents/bin")
endif()
set(ninja_url "https://github.com/ninja-build/ninja/releases/download/v${ninja_version}/ninja-${ninja_suffix}")
file(DOWNLOAD "${ninja_url}" ./ninja.zip SHOW_PROGRESS)
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xvf ./ninja.zip)
set(cmake_url "https://github.com/Kitware/CMake/releases/download/v${cmake_version}/cmake-${cmake_version}-${cmake_suffix}")
file(DOWNLOAD "${cmake_url}" ./cmake.zip SHOW_PROGRESS)
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xvf ./cmake.zip)
# Save the path for other steps
file(TO_CMAKE_PATH "$ENV{GITHUB_WORKSPACE}/${cmake_dir}" cmake_dir)
message("::set-output name=cmake_dir::${cmake_dir}")
if (NOT "${{ runner.os }}" STREQUAL "Windows")
execute_process(
COMMAND chmod +x ninja
COMMAND chmod +x ${cmake_dir}/cmake
)
endif()
- name: Configure
shell: cmake -P {0}
run: |
set(ENV{CC} ${{ matrix.config.cc }})
set(ENV{CXX} ${{ matrix.config.cxx }})
if ("${{ runner.os }}" STREQUAL "Windows" AND NOT "x${{ matrix.config.environment_script }}" STREQUAL "x")
execute_process(
COMMAND "${{ matrix.config.environment_script }}" && set
OUTPUT_FILE environment_script_output.txt
)
file(STRINGS environment_script_output.txt output_lines)
foreach(line IN LISTS output_lines)
if (line MATCHES "^([a-zA-Z0-9_-]+)=(.*)$")
set(ENV{${CMAKE_MATCH_1}} "${CMAKE_MATCH_2}")
endif()
endforeach()
endif()
file(TO_CMAKE_PATH "$ENV{GITHUB_WORKSPACE}/ninja" ninja_program)
execute_process(
COMMAND ${{ steps.cmake_and_ninja.outputs.cmake_dir }}/cmake
-S .
-B build
-D CMAKE_BUILD_TYPE=${{ matrix.config.build_type }}
-G Ninja
-D CMAKE_MAKE_PROGRAM=${ninja_program}
RESULT_VARIABLE result
)
if (NOT result EQUAL 0)
message(FATAL_ERROR "Bad exit status")
endif()
- name: Build
shell: cmake -P {0}
run: |
set(ENV{NINJA_STATUS} "[%f/%t %o/sec] ")
if ("${{ runner.os }}" STREQUAL "Windows" AND NOT "x${{ matrix.config.environment_script }}" STREQUAL "x")
file(STRINGS environment_script_output.txt output_lines)
foreach(line IN LISTS output_lines)
if (line MATCHES "^([a-zA-Z0-9_-]+)=(.*)$")
set(ENV{${CMAKE_MATCH_1}} "${CMAKE_MATCH_2}")
endif()
endforeach()
endif()
execute_process(
COMMAND ${{ steps.cmake_and_ninja.outputs.cmake_dir }}/cmake --build build
RESULT_VARIABLE result
)
if (NOT result EQUAL 0)
message(FATAL_ERROR "Bad exit status")
endif()
- name: Install Strip
run: ${{ steps.cmake_and_ninja.outputs.cmake_dir }}/cmake --install build --prefix instdir --strip


- name: Pack
working-directory: instdir
run: ${{ steps.cmake_and_ninja.outputs.cmake_dir }}/cmake -E tar cJfv ../${{ matrix.config.artifact }} .


- name: Upload
uses: actions/upload-artifact@v1
with:
path: ./${{ matrix.config.artifact }}
name: ${{ matrix.config.artifact }}

release:
if: contains(github.ref, 'tags/v')
runs-on: ubuntu-latest
needs: build

steps:
- name: Create Release
id: create_release
uses: actions/create-release@v1.0.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: Release ${{ github.ref }}
draft: false
prerelease: false

- name: Store Release url
run: |
echo "${{ steps.create_release.outputs.upload_url }}" > ./upload_url
- uses: actions/upload-artifact@v1
with:
path: ./upload_url
name: upload_url

publish:
if: contains(github.ref, 'tags/v')
name: ${{ matrix.config.name }}
runs-on: ${{ matrix.config.os }}
strategy:
fail-fast: false
matrix:
config:
- {
name: "Windows Latest MSVC", artifact: "Windows-MSVC.tar.xz",
os: ubuntu-latest
}
- {
name: "Windows Latest MinGW", artifact: "Windows-MinGW.tar.xz",
os: ubuntu-latest
}
- {
name: "Ubuntu Latest GCC", artifact: "Linux.tar.xz",
os: ubuntu-latest
}
- {
name: "macOS Latest Clang", artifact: "macOS.tar.xz",
os: ubuntu-latest
}
needs: release

steps:
- name: Download artifact
uses: actions/download-artifact@v1
with:
name: ${{ matrix.config.artifact }}
path: ./

- name: Download URL
uses: actions/download-artifact@v1
with:
name: upload_url
path: ./
- id: set_upload_url
run: |
upload_url=`cat ./upload_url`
echo ::set-output name=upload_url::$upload_url
- name: Upload to Release
id: upload_to_release
uses: actions/upload-release-asset@v1.0.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.set_upload_url.outputs.upload_url }}
asset_path: ./${{ matrix.config.artifact }}
asset_name: ${{ matrix.config.artifact }}
asset_content_type: application/x-gtar
8 changes: 7 additions & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
[submodule "external/asmjit"]
path = external/asmjit
url = git@github.com:asmjit/asmjit.git
url=https://github.com/asmjit/asmjit.git
[submodule "external/fmt"]
path = external/fmt
url = https://github.com/fmtlib/fmt.git
[submodule "external/capstone"]
path = external/capstone
url = https://github.com/aquynh/capstone.git
7 changes: 6 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
cmake_minimum_required(VERSION 3.13.4)
project(AheuiJIT)

option(BUILD_CLI "Build CLI" ON)

set_property(GLOBAL PROPERTY USE_FOLDERS ON)

set(CMAKE_CXX_STANDARD 17)
Expand All @@ -9,4 +11,7 @@ set(CMAKE_CXX_EXTENSIONS OFF)

add_subdirectory(external)
add_subdirectory(src/AheuiJIT)
add_subdirectory(src/AheuiJIT/Sample)

if (BUILD_CLI)
add_subdirectory(src/AheuiJIT/Cli)
endif()
65 changes: 65 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# 아희짓

## Brief English introduction

AheuiJIT is a just in time compiler for [Aheui language](https://aheui.readthedocs.io/en/latest/specs.en.html) built from scratch. Its design is inspired by LLVM and dynarmic project.

## 개요

아희짓은 [아희 언어](https://aheui.readthedocs.io/en/latest/introduction.html)를 위한 JIT (Just in Time) 컴파일러입니다. 어셈블러와 유틸 라이브러리외에 외부 라이브러리에 전혀 의존하지 않고 JIT을 바닥부터 구현합니다.

## 지원 사양

현재 64비트 x86 운영체제 만 지원합니다. 제작자가 시간이 생긴다면 ARM도 지원할 예정입니다.

## 사용법

릴리즈 페이즈에 가서 운영체제에 맞는 압축파일을 다운받고 압축을 푸세요.
```
bin/AheuiJITCli 아희파일
```
로 아희 프로그램을 실행해볼 수 있습니다.

inlcude와 lib폴더에는 정적 라이브러리로 빌드된 AheuiJIT이 있습니다.

## 구현 완성도

![](tests.png)

[아희 테스트 케이스](https://github.com/aheui/snippets) 중 64 비트 정수 출력을 제외한 모든 테스트를 통과합니다.

## 성능

logo 아희 테스트를 0.29초 안에 완료합니다. 이는 [기존 비교표](http://xnuk.github.io/Comparison-of-aheui-implementations/) 기준 Algy/aheui-cc (0.11초)를 제외한 모든 구현체보다 월등히 빠른 속도입니다.

```
/usr/bin/time AheuiJITCli logo.aheui > out.out
0.29 real 0.29 user 0.00 sys
```

## 빌드

C++17을 지원하는 컴파일러와 cmake을 깔고 아래 명령어를 실행하면 됩니다.

```
git submodul update --init
mkdir build
cd buildㅌ
cmake ..
```

## TODOs

현재 기본적인 최적화만 구현된 상태입니다. 이정도로도 엄청나게 빠르지만 더 빨라질 여지가 많습니다.

### pop optimization

연산자가 저장소의 모든 원소를 다 사용한 경우 반대 방향으로 이동해야하는 아희 명세를 구현하기 위해 저장소 pop 연산이 약간 비효율적으로 구현되어있습니다. 저장소 끝자락 페이지의 읽기 권한을 없애고 예외 헨들러를 달아서 저장소 잔여 공간 체크 루틴을 없애버릴 수 있습니다. GPU 드라이버가 텍스쳐 캐시를 구현할 때 자주 쓰는 기법입니다. 저장소 소진이 매우 자주 일어난다면 더 느리겠지만 이 경우 기존 체크 루틴을 사용하게 다시 컴파일 하는 식으로 대응할 수 있습니다.

### instruction scheduling

logo 테스트 같이 커다란 아희 프로그램에서 연산자를 좀더 잘 나열하면 메모리를 선형으로 참조 & 갱신하게 만들 수 있을 것 같습니다. 이러면 vectorization을 할 여지도 생깁니다.

### inline basic block

push와 pop을 매칭하는 peephole 최적화는 굉장히 효과적입니다. 이 최적화를 끄고 logo 테스트 케이스를 돌리면 15초씩이나 걸립니다. 이 최적화는 특성상 basic block 크기가 클수록 더 효과가 커지는데 여러 basic block을 합치는 식으로 효과를 더 증대할 수 있습니다.
14 changes: 0 additions & 14 deletions design.md

This file was deleted.

Loading

0 comments on commit 84faa38

Please sign in to comment.