Giter VIP home page Giter VIP logo

tonlabs / tvm-compiler Goto Github PK

View Code? Open in Web Editor NEW
60.0 9.0 16.0 632.74 MB

Clang compiler for TVM

License: Apache License 2.0

Dockerfile 0.01% Shell 0.03% CMake 0.19% Go 0.04% C++ 44.90% OCaml 0.12% Python 0.51% CSS 0.01% Batchfile 0.01% Roff 0.01% C 6.85% Pawn 0.01% LLVM 32.41% Assembly 12.15% Objective-C 1.73% HTML 0.44% Swift 0.01% Objective-C++ 0.50% Cuda 0.09% Rust 0.01%
llvm clang everscale blockchain

tvm-compiler's Introduction

C and C++ compiler for TVM

Getting C++ toolchain in binary form This README is mostly about building C++ for TVM which is the most appropriate way to get the compiler and the library for contributors. If your intent is only to use the compiler, we provide binary package you can simply download:

The binaries are updated on every commit in master, so they are always up to date.

Clang for TVM based on LLVM 7.0.0. This repository contain

Prerequisites

To build the toolchain, you need a recent C++ toolchain supporting C++17:

  • MSVC 2017 or newer
  • Clang 6.0.0 or newer
  • GCC 7.3.0 or newer
  • Rust 1.47.0 or newer
  • Cargo

Stable operation of older toolchains is not guaranteed. You also need zlib 1.2.3.4 or newer. Python 2.7 is required to run tests. Optionally, you can use ninja-build. For more info about LLVM software requirements visit: https://llvm.org/docs/GettingStarted.html.

Supported operation systems

We expect the project to build successfully on

  • Ubuntu 16.04, 18.04
  • Mac OS Mojave 10.14.3 or higher
  • Windows 10

Building and installing

To build and to install the compiler use the following script:

$ git clone [email protected]:tonlabs/TON-Compiler.git && cd TON-Compiler
$ mkdir build
$ cd build
$ cmake -DCMAKE_INSTALL_PREFIX=/path/to/install -C /path/to/TON-Compiler/cmake/Cache/ton-compiler.cmake ../llvm
$ cmake --build . --target install-distribution

Notes:

  • /path/to/install must be complete path to the installation folder, otherwise Clang might be unable to find all the libraries, headers and tools by default.
  • We strongly recommend to use the installed version of the compiler, otherwise it might be unable to find the required headers and tools by itself, so they have to be specified by hands.
  • A complete C and C++ toolchain require tvm_linker to be built. We recommend to put the liker binary to /path/to/install/bin directory. Otherwise you might need to use -fuse-ld option to spicify full name of the linker.
  • install-distribution installs only required minimum of tools, while install target copies all the LLVM tools to the installation folder. These additional tools doesn't necessary work with TVM target properly.

For Windows / Microsoft Visual Studio 2017/2020 (clang Compiler without linker & other external tools)

> git clone [email protected]:tonlabs/TON-Compiler.git && cd TON-Compiler
> mkdir build
> cd build
> cmake -G "Visual Studio 15" -DLLVM_TARGETS_TO_BUILD="TVM" -C /path/to/TON-Compiler/cmake/Cache/ton-compiler-alone.cmake ../llvm

Then open generated solution file LLVM.sln with Visual Studio

Troubleshooting and speeding up the build

Building Clang takes quite a bit of time, below we list some options to speed it up:

  • Use faster build system via -GXXX option. We recommend to choose ninja-build (you might need to install it first) using -GNinja.
  • Use a faster linker via -DCMAKE_LINKER=<linker name>. It's known that lld is faster than gold, and gold is faster than ld. On Linux, however, lld might not be a part of the default toolchain, so you might have to install it first.
  • Use a faster compiler via -DCMAKE_C_COMPILER=<compiler> and -DCMAKE_CXX_COMPILER=<compiler>. Clang might be slightly faster than GCC.
  • Build dynamically linked version of Clang via -DBUILD_SHARED_LIB=On. Note that building Clang also require a tens of gigabytes of disk space (especially for a static build) and several gigabytes of RAM to be build. In case, you run out of memory -DLLVM_PARALLEL_LINK_JOBS=N might be of help. This option limits the number of link jobs running in parallel does the footpring. There is also a separate option -DLLVM_PARALLEL_COMPILE_JOBS=N to limit number of compilation jobs running in parallel. To learn more about possible configurations of LLVM build, please refer to LLVM documentation. In case you are experiencing problems with build, we would appreciete raising an issue in this repository.

Running tests

To run tests for TVM, execute

$ cmake --build . --target check-llvm-codegen-tvm

To run tests for other platforms (to ensure that LLVM itself is not broken), you have to create a separate build without using /path/to/TON-Compiler/cmake/Cache/ton-compiler.cmake config and run

$ cmake --build . --target check all

For more details see testing.md.

Example of usage

You can learn more about C++ for TVM and find examples of usage of C++ toolchain here. C toolchain is mostly for geeks who want to follow TVM assembly closely, but doesn't want to work with stack. C examples might be found here.

Getting support

C and C++ for TVM, being similar to conventional C and C++, has their own extensions and limitations, so if you are getting started with programming for TVM, we recommend to first refer to the examples repository. Texts, videos and samples illustrating how to use the compiler will soon appear at https://ton.dev/ and https://www.youtube.com/channel/UC9kJ6DKaxSxk6T3lEGdq-Gg. Stay tuned. You can also get support in TON Dev Telegram channel. In case you found a bug, raise an issue in the repository. Please attach the source file, the command to reproduce the failure and your machine description.

Contribution policy

The project strives to follow LLVM coding standards and policies as well as C++ Core Guidelines, so before contributing, we recommend you to familiarize with the following documents:

Note: Since TVM backend uses C++17 which is not yet fully supported in LLVM, the guidelines could be reasonably adjusted for cases of C++17 usages. C++17 data structures are preferred over LLVM counterparts, for instance, std::optional<T> is better to use w.r.t. llvm::Optional<T>.

All changes in LLVM (excluding lib/Target/TVM subdirectory) must be marked as local changes in the following way:

// TVM local begin
<changed LLVM code>
// TVM local end

The reason is to help resolving merge conflicts when updating LLVM to a new version.

All removals from LLVM must be commented out instead:

#if 0
<removed LLVM code>
#endif

The reason is to minimize number of merge conflicts when updating LLVM to a new version. To learn more about development a downstream LLVM project, refer to https://llvm.org/devmtg/2015-10/slides/RobinsonEdwards-LivingDownstreamWithoutDrowning.pdf.

Upstreaming

We believe that LLVM community would benefit from getting TVM backend upstream. It's a very distinct architecture, that break several assumptions. For instance, Clang front-end and the optimizer relies on 8-bit bytes byte which is not true for TVM as well as for some non-mainstream processors. Furthermore, target independent code generator is designed for a register machine, so stack machine support is benefitial at least for WebAssembly. So, with some constraints removed, LLVM will be better placed to downstream development and we believe it is feasible without damaging existing targets. We would like to implement, upstream and maintain the following features:

  • Byte size specified in data layout, removing magical number 8 from the optimizer.
  • memset, memcopy, memmove configured with the byte size.
  • DAG scheduler for a stack machine.
  • Generic analysis and transformation passes to optimize for stack machine on MIR level. The current version of Clang for TVM is based on LLVM 7.0.0, it's planned update LLVM, remove hardcoded byte size and adopt opaque types insted of types we introduced to LLVM.

tvm-compiler's People

Contributors

akyrtzi avatar arsenm avatar chandlerc avatar chapuni avatar d0k avatar ddunbar avatar dexonsmith avatar djasper avatar douggregor avatar dwblaikie avatar echristo avatar eefriedman avatar ericwf avatar espindola avatar isanbard avatar kcc avatar lattner avatar majnemer avatar nlewycky avatar resistor avatar rjmccall avatar rksimon avatar rnk avatar rotateright avatar rui314 avatar stoklund avatar tkremenek avatar tobiasgrosser avatar topperc avatar zygoloid avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tvm-compiler's Issues

An ISel failure related to the builder type

target datalayout = "E-S257-i1:257:257-i8:257:257-i16:257:257-i32:257:257-i64:257:257-i257:257:257-p:257:257-a:257:257"
target triple = "tvm"

define void @foo(builder* %builder) {
entry:
  %b = load builder, builder* %builder, align 1
  %b_prime = call builder @llvm.tvm.stu(i257 1, builder %b, i257 1)
  store builder %b_prime, builder* %builder, align 1
  ret void
}

declare builder @llvm.tvm.stu(i257, builder, i257)
LLVM ERROR: Cannot select: t13: ch = store<(store 1 into %ir.builder)> t9:1, t12, t2, undef:i257
  t12: TVMBuilder = llvm.tvm.stu TargetConstant:i257<5491>, Constant:i257<1>, t9, Constant:i257<1>
    t10: i257 = TargetConstant<5491>
    t11: i257 = Constant<1>
    t9: TVMBuilder,ch = load<(load 1 from %ir.builder)> t7, t2, undef:i257
      t2: i257 = TVMISD::ARGUMENT TargetConstant:i257<0>
        t1: i257 = TargetConstant<0>
      t8: i257 = undef
    t11: i257 = Constant<1>
  t2: i257 = TVMISD::ARGUMENT TargetConstant:i257<0>
    t1: i257 = TargetConstant<0>
  t8: i257 = undef
In function: foo

Fail on Building and installing

git c --dept 1 [email protected]:tonlabs/TON-Compiler.git
mkdir -p TON-Compiler/build $HOME/bin/ton
cd TON-Compiler/build
cmake -DCMAKE_INSTALL_PREFIX=$HOME/bin/ton -C /path/to/TON-Compiler/cmake/Cache/ton-compiler.cmake ../llvm
cmake --build . --target install-distribution

Out

make: *** No rule to make target 'install-distribution'.  Stop.

Suboptimal code generation for simple loop

int gcd(int a, int b)
{
  int r;
  while (b > 0)
  {
    r = a % b;
    a = b;
    b = r;
  }
  return a;
}

define dso_local i257 @gcd(i257 %a, i257 %b) {
entry:
  %cmp3 = icmp sgt i257 %b, 0
  br i1 %cmp3, label %while.body, label %while.end

while.body:                                       ; preds = %entry, %while.body
  %a.addr.05 = phi i257 [ %b.addr.04, %while.body ], [ %a, %entry ]
  %b.addr.04 = phi i257 [ %rem, %while.body ], [ %b, %entry ]
  %rem = srem i257 %a.addr.05, %b.addr.04
  %cmp = icmp sgt i257 %rem, 0
  br i1 %cmp, label %while.body, label %while.end

while.end:                                        ; preds = %while.body, %entry
  %a.addr.0.lcssa = phi i257 [ %a, %entry ], [ %b.addr.04, %while.body ]
  ret i257 %a.addr.0.lcssa
}

gcd:                                    ; @gcd
; %bb.0:                                ; %entry
                                        ; { %20 | %1 | - }
	PUSH	c0                      ; >%4 = PUSHC i257 0
                                        ; { %20 | %1 | %4 | - }
	PUSHINT	0                       ; >%27 = CONST_I257 i257 0
                                        ; { %20 | %1 | %4 | %27 | - }
	PUSH	s2                      ; { %20 | %1 | %4 | %27 | %1 | - }
	SWAP                            ; { %20 | %1 | %4 | %1 | %27 | - }
	GREATER                         ; >%8 = SGT %1, %27
                                        ; { %20 | %1 | %4 | %8 | - }
	PUSHCONT                        ; >%19 = PUSHCONT_MBB %bb.2, 0
                                        ; { %20 | %1 | %4 | %8 | %19 | - }
	{
; %bb.2:                                ; %while.end
                                        ; { %1 | x | %4 | x | x | - }
	  BLKDROP	2               ; { %1 | x | %4 | - }
	  POP	c0                      ; { %1 | x | - }
	  DROP                          ; { %1 | - }
                                        ; fallthrough return
	  
	}
	PUSHCONT                        ; >%24 = PUSHCONT_MBB %bb.5, 0
                                        ; { %20 | %1 | %4 | %8 | %19 | %24 | - }
	{
; %bb.5:                                ; %entry.while.end.cleanup
                                        ; { x | %4 | %19 | %20 | - }
	                                ; >%1 = REG_TO_REG_COPY %20
                                        ; { x | %4 | %19 | %1 | - }
	  ZERO                          ; { x | %4 | %19 | %1 | x | - }
	  ZERO                          ; { x | %4 | %19 | %1 | x | x | - }
	  ROLLREV	2               ; { x | %4 | %19 | x | %1 | x | - }
	  BLKSWAP	2, 4            ; { %19 | x | %1 | x | x | %4 | - }
	  SWAP                          ; { %19 | x | %1 | x | %4 | x | - }
	  ROLL	4                       ; { %19 | %1 | x | %4 | x | x | - }
	  ROLL	5                       ; { %1 | x | %4 | x | x | %19 | - }
	  JMPX                          ; { %1 | x | %4 | x | x | %19 | - } => { %1 | x | %4 | x | x | - }
	}
	BLKSWAP	2, 3                    ; { %20 | %8 | %19 | %24 | %1 | %4 | - }
	ROLL	3                       ; { %20 | %8 | %24 | %1 | %4 | %19 | - }
	ROLL	5                       ; { %8 | %24 | %1 | %4 | %19 | %20 | - }
	ROLL	5                       ; { %24 | %1 | %4 | %19 | %20 | %8 | - }
	ROLL	5                       ; { %1 | %4 | %19 | %20 | %8 | %24 | - }
	IFNOTJMP                        ; { %1 | %4 | %19 | %20 | %8 | %24 | - } => { %1 | %4 | %19 | %20 | - }
; %bb.1:                                ; %entry.while.body.cleanup
                                        ; { %1 | %4 | %19 | %20 | - }
	PUSHCONT                        ; >%12 = PUSHCONT_MBB %bb.3, i257 0
                                        ; { %1 | %4 | %19 | %20 | %12 | - }
	{
; %bb.3:                                ; %while.body
                                        ; { %1 | %4 | %12 | %19 | %20 | - }
	  PUSH	s4                      ; { %1 | %4 | %12 | %19 | %20 | %1 | - }
	  MOD                           ; >%2 = MOD %20, %1
                                        ; { %1 | %4 | %12 | %19 | %2 | - }
	  PUSHINT	0               ; >%28 = CONST_I257 i257 0
                                        ; { %1 | %4 | %12 | %19 | %2 | %28 | - }
	  PUSH	s1                      ; { %1 | %4 | %12 | %19 | %2 | %28 | %2 | - }
	  SWAP                          ; { %1 | %4 | %12 | %19 | %2 | %2 | %28 | - }
	  GREATER                       ; >%14 = SGT %2, %28
                                        ; { %1 | %4 | %12 | %19 | %2 | %14 | - }
	  PUSHCONT
	  {
; %bb.4:                                ; %while.body.while.body.cleanup
                                        ; { %1 | %2 | %4 | %12 | %19 | - }
	    XCHG	s0, s4          ; { %19 | %2 | %4 | %12 | %1 | - }
	                                ; >%20 = REG_TO_REG_COPY %1
                                        ; { %19 | %2 | %4 | %12 | %20 | - }
	    XCHG	s0, s3          ; { %19 | %20 | %4 | %12 | %2 | - }
	                                ; >%1 = REG_TO_REG_COPY %2
                                        ; { %19 | %20 | %4 | %12 | %1 | - }
	    PUSH	s1              ; { %19 | %20 | %4 | %12 | %1 | %12 | - }
	    SWAP                        ; { %19 | %20 | %4 | %12 | %12 | %1 | - }
	    BLKSWAP	2, 2            ; { %19 | %20 | %12 | %1 | %4 | %12 | - }
	    BLKSWAP	2, 4            ; { %12 | %1 | %4 | %12 | %19 | %20 | - }
	    ROLL	5               ; { %1 | %4 | %12 | %19 | %20 | %12 | - }
	    JMPX                        ; { %1 | %4 | %12 | %19 | %20 | %12 | - } => { %1 | %4 | %12 | %19 | %20 | - }
	  }                             ; >%26 = PUSHCONT_MBB %bb.4, 0
                                        ; { %1 | %4 | %12 | %19 | %2 | %14 | %26 | - }
	  PUSH	s3                      ; { %1 | %4 | %12 | %19 | %2 | %14 | %26 | %19 | - }
	  ROLL	3                       ; { %1 | %4 | %12 | %19 | %14 | %26 | %19 | %2 | - }
	  BLKSWAP	3, 4            ; { %1 | %14 | %26 | %19 | %2 | %4 | %12 | %19 | - }
	  BLKSWAP	3, 4            ; { %1 | %2 | %4 | %12 | %19 | %14 | %26 | %19 | - }
	  IFELSE                        ; { %1 | %2 | %4 | %12 | %19 | %14 | %26 | %19 | - } => { %1 | %2 | %4 | %12 | %19 | - }
	}
	DUP                             ; { %1 | %4 | %19 | %20 | %12 | %12 | - }
	SWAP                            ; { %1 | %4 | %19 | %20 | %12 | %12 | - }
	BLKSWAP	2, 2                    ; { %1 | %4 | %12 | %12 | %19 | %20 | - }
	ROLL	3                       ; { %1 | %4 | %12 | %19 | %20 | %12 | - }
	JMPX                            ; { %1 | %4 | %12 | %19 | %20 | %12 | - } => { %1 | %4 | %12 | %19 | %20 | - }

AddressSanitizer: use-after-poison

target datalayout = "E-S257-i1:257:257-i8:257:257-i16:257:257-i32:257:257-i64:257:257-i257:257:257-p:257:257-a:257:257"
target triple = "tvm"
define void @foo(i257 %v) {
entry:
  %cmp = icmp eq i257 %v, 0
  br i1 %cmp, label %then, label %else
then:
  ret void
else:
  ret void
}
=================================================================
==15025==ERROR: AddressSanitizer: use-after-poison on address 0x621000011e90 at pc 0x7f0739ad3fe5 bp 0x7ffe72f6a780 sp 0x7ffe72f6a778
READ of size 4 at 0x621000011e90 thread T0
    #0 0x7f0739ad3fe4 in llvm::MachineBasicBlock::getNumber() const /tonlabs/TON-Compiler/llvm/include/llvm/CodeGen/MachineBasicBlock.h:770:34
    #1 0x7f0739e8046e in llvm::MachineBasicBlock::printAsOperand(llvm::raw_ostream&, bool) const /tonlabs/TON-Compiler/llvm/lib/CodeGen/MachineBasicBlock.cpp:433:19
    #2 0x7f0739aa299b in llvm::operator<<(llvm::raw_ostream&, llvm::Printable const&) /tonlabs/TON-Compiler/llvm/include/llvm/Support/Printable.h:46:3
    #3 0x7f073a024121 in llvm::MachineOperand::print(llvm::raw_ostream&, llvm::ModuleSlotTracker&, llvm::LLT, bool, bool, bool, unsigned int, llvm::TargetRegisterInfo const*, llvm::TargetIntrinsicInfo const*) const /tonlabs/TON-Compiler/llvm/lib/CodeGen/MachineOperand.cpp:793:8
    #4 0x7f073a023c24 in llvm::MachineOperand::print(llvm::raw_ostream&, llvm::LLT, llvm::TargetRegisterInfo const*, llvm::TargetIntrinsicInfo const*) const /tonlabs/TON-Compiler/llvm/lib/CodeGen/MachineOperand.cpp:715:3
    #5 0x7f073a023a36 in llvm::MachineOperand::print(llvm::raw_ostream&, llvm::TargetRegisterInfo const*, llvm::TargetIntrinsicInfo const*) const /tonlabs/TON-Compiler/llvm/lib/CodeGen/MachineOperand.cpp:707:3
    #6 0x7f073cb3cbff in llvm::operator<<(llvm::raw_ostream&, llvm::MachineOperand const&) /tonlabs/TON-Compiler/llvm/include/llvm/CodeGen/MachineOperand.h:948:6
    #7 0x7f073cb3c807 in (anonymous namespace)::TVMStackModel::prepareInstructionComment[abi:cxx11](llvm::MachineInstr const&) const::$_11::operator()(llvm::MachineOperand const&) const /tonlabs/TON-Compiler/llvm/lib/Target/TVM/TVMStackModel.cpp:174:10
    #8 0x7f073cb3b565 in (anonymous namespace)::TVMStackModel::prepareInstructionComment[abi:cxx11](llvm::MachineInstr const&) const /tonlabs/TON-Compiler/llvm/lib/Target/TVM/TVMStackModel.cpp:190:5
    #9 0x7f073cb316bd in (anonymous namespace)::TVMStackModel::rewriteToSForm(llvm::MachineInstr&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, llvm::Stack&) /tonlabs/TON-Compiler/llvm/lib/Target/TVM/TVMStackModel.cpp:700:49
    #10 0x7f073cb2edb1 in (anonymous namespace)::TVMStackModel::processInstruction(llvm::MachineInstr&, llvm::Stack&) /tonlabs/TON-Compiler/llvm/lib/Target/TVM/TVMStackModel.cpp:271:3
    #11 0x7f073cb1e536 in (anonymous namespace)::TVMStackModel::runOnBasicBlocks(llvm::MachineFunction&, llvm::Stack const&) /tonlabs/TON-Compiler/llvm/lib/Target/TVM/TVMStackModel.cpp:294:18
    #12 0x7f073cb1bd3f in (anonymous namespace)::TVMStackModel::runOnMachineFunction(llvm::MachineFunction&) /tonlabs/TON-Compiler/llvm/lib/Target/TVM/TVMStackModel.cpp:513:7
    #13 0x7f0739fa2c55 in llvm::MachineFunctionPass::runOnFunction(llvm::Function&) /tonlabs/TON-Compiler/llvm/lib/CodeGen/MachineFunctionPass.cpp:61:13
    #14 0x7f07386f6683 in llvm::FPPassManager::runOnFunction(llvm::Function&) /tonlabs/TON-Compiler/llvm/lib/IR/LegacyPassManager.cpp:1586:27
    #15 0x7f07386f6e26 in llvm::FPPassManager::runOnModule(llvm::Module&) /tonlabs/TON-Compiler/llvm/lib/IR/LegacyPassManager.cpp:1609:16
    #16 0x7f07386f796e in (anonymous namespace)::MPPassManager::runOnModule(llvm::Module&) /tonlabs/TON-Compiler/llvm/lib/IR/LegacyPassManager.cpp:1669:27
    #17 0x7f07386f7266 in llvm::legacy::PassManagerImpl::run(llvm::Module&) /tonlabs/TON-Compiler/llvm/lib/IR/LegacyPassManager.cpp:1774:44
    #18 0x34555a in compileModule(char**, llvm::LLVMContext&) /tonlabs/TON-Compiler/llvm/tools/llc/llc.cpp:597:8
    #19 0x342c53 in main /tonlabs/TON-Compiler/llvm/tools/llc/llc.cpp:351:22
    #20 0x7f0732dce1e2 in __libc_start_main /build/glibc-4WA41p/glibc-2.30/csu/../csu/libc-start.c:308:16
    #21 0x28902d in _start (/tonlabs/TON-Compiler/sanitized/bin/llc+0x28902d)

Illegal reordering of instructions

The following input

target datalayout = "E-S257-i1:257:257-i8:257:257-i16:257:257-i32:257:257-i64:257:257-i257:257:257-p:257:257-a:257:257"
target triple = "tvm"

define void @foo(i257 %v, slice %t11) {
entry:
  call void @llvm.tvm.throwif(i257 %v, i257 59)
  %i31 = extractvalue { i257, slice } %t13, 1
  %t14 = call { i257, slice } @llvm.tvm.ldu(slice %i31, i257 2)
  %i29 = extractvalue { i257, slice } %t14, 1
  %t15 = call { i257, slice } @llvm.tvm.ldu(slice %i29, i257 3)
  %i27 = extractvalue { i257, slice } %t15, 1
  %t16 = call { i257, slice } @llvm.tvm.ldu(slice %i27, i257 4)
  %i25 = extractvalue { i257, slice } %t16, 1
  %t17 = call { i257, slice } @llvm.tvm.ldu(slice %i25, i257 5)
  %i23 = extractvalue { i257, slice } %t17, 1
  %t18 = call { i257, slice } @llvm.tvm.ldu(slice %i23, i257 6)
  %i21 = extractvalue { i257, slice } %t18, 1
  %t19 = call { i257, slice } @llvm.tvm.ldu(slice %i21, i257 7)
  %t10 = extractvalue { i257, slice } %t19, 0
  %cmp = icmp ne i257 %t10, 1
  %ext = zext i1 %cmp to i257
  call void @llvm.tvm.throwif(i257 %ext, i257 59)
  ret void
}

declare void @llvm.tvm.throwif(i257, i257)
declare { i257, slice } @llvm.tvm.ldu(slice, i257)

gets translated to

foo:
  LDU  1
  LDU  2
  LDU  3
  XCHG  s0, s4
  THROWIF 59
  BLKDROP 3
  LDU  4
  LDU  5
  LDU  6
  LDU  7
  PUSHINT 1
  XCHG  s1, s2
  NEQ
  PUSHINT 1
  AND
  THROWIF 59
  BLKDROP 4

First THROWIF gets moved down after possibly throwing LDUs.

git clone [email protected]:tonlabs/TON-Compiler.git error

freeton:~/ton# git clone [email protected]:tonlabs/TON-Compiler.git
Cloning into 'TON-Compiler'...
The authenticity of host 'github.com (140.82.121.3)' can't be established.
RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8.
Are you sure you want to continue connecting (yes/no)? y
Please type 'yes' or 'no': yes
Warning: Permanently added 'github.com,140.82.121.3' (RSA) to the list of known hosts.
[email protected]: Permission denied (publickey).
fatal: Could not read from remote repository.

Work fine:
git clone https://github.com/tonlabs/TON-Compiler.git

Bitfields are not compiled correctly

While TVM-llvm only supports i257 type, in bit fields, it still chooses types like i128.

Reproduce Instructions:

Contract.cpp

struct my_bitfield{
  unsigned field: 128;
};
int main(){
  my_bitfield c;
  c.field =1;
}

compile command:

/path/to/toolchain/opt/work/llvm/install/bin/clang++ -target tvm -O0 -S -emit-llvm Contract.cpp \
-o ir-code.ll --sysroot=/path/to/toolchain/opt/work/llvm/install/bin/..

Note: The -O0 is important, -O3 would optimize the problem away in simple cases such as this example.

Resulting IR code:

; ModuleID = 'src/Contract.cpp'
source_filename = "src/Contract.cpp"
target datalayout = "E-S257-i1:257:257-i8:257:257-i16:257:257-i32:257:257-i64:257:257-i257:257:257-p:257:257-a:257:257"
target triple = "tvm"

%struct.my_bitfield = type { i128 }

; Function Attrs: noinline norecurse nounwind optnone
define dso_local i257 @main() #0 {
  %1 = alloca %struct.my_bitfield, align 1
  %2 = bitcast %struct.my_bitfield* %1 to i257*
  %3 = load i257, i257* %2, align 1
  %4 = and i257 %3, 680564733841876926926749214863536422911
  %5 = or i257 %4, 680564733841876926926749214863536422912
  store i257 %5, i257* %2, align 1
  ret i257 0
}

attributes #0 = { noinline norecurse nounwind optnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }

!llvm.module.flags = !{!0}
!llvm.ident = !{!1}

!0 = !{i32 1, !"wchar_size", i32 1}
!1 = !{!"TON Labs clang for TVM. Version 7.7.22  (based on LLVM 7.7.22)"}

Note the "i128" in line number 4.

A failure in TVMStackFixup

target datalayout = "E-S257-i1:257:257-i8:257:257-i16:257:257-i32:257:257-i64:257:257-i257:257:257-p:257:257-a:257:257"
target triple = "tvm"
define void @bar() {
entry:
  %0 = call i257 @foo(i257 0)
  %1 = call i257 @foo(i257 1)
  %2 = call i257 @foo(i257 2)
  %3 = call i257 @foo(i257 3)
  %4 = call i257 @foo(i257 4)
  call void @llvm.tvm.throwif(i257 undef, i257 61)
  br label %exit
exit:
  ret void
}
declare void @llvm.tvm.throwif(i257, i257)
declare i257 @foo(i257)
#10 0x00007f0b555cf2a3 decltype(adl_begin(fp)) llvm::find_or_fail<std::deque<llvm::StackVreg, std::allocator<llvm::StackVreg> > const&, llvm::StackVreg>(std::deque<llvm::StackVreg, std::allocator<llvm::StackVreg> > const&, llvm::StackVreg const&) /home/mskvortsov/tonlabs/TON-Compiler/llvm/lib/Target/TVM/TVMExtras.h:0:3
#11 0x00007f0b555cda5b llvm::Stack::position(llvm::StackVreg const&) const /home/mskvortsov/tonlabs/TON-Compiler/llvm/lib/Target/TVM/TVMStack.h:103:12
#12 0x00007f0b555e3099 llvm::StackFixup::Diff(llvm::Stack const&, llvm::Stack const&)::$_28::operator()(llvm::StackVreg const&) const /home/mskvortsov/tonlabs/TON-Compiler/llvm/lib/Target/TVM/TVMStackFixup.cpp:92:10
#13 0x00007f0b555e2fc3 llvm::StackFixup::Diff(llvm::Stack const&, llvm::Stack const&)::$_28 std::for_each<llvm::StackVreg*, llvm::StackFixup::Diff(llvm::Stack const&, llvm::Stack const&)::$_28>(llvm::StackVreg*, llvm::StackVreg*, llvm::StackFixup::Diff(llvm::Stack const&, llvm::Stack const&)::$_28) /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_algo.h:3875:33
#14 0x00007f0b555dac16 llvm::StackFixup::Diff(llvm::Stack const&, llvm::Stack const&)::$_28 llvm::for_each<llvm::SmallVector<llvm::StackVreg, 16u>&, llvm::StackFixup::Diff(llvm::Stack const&, llvm::Stack const&)::$_28>(llvm::SmallVector<llvm::StackVreg, 16u>&, llvm::StackFixup::Diff(llvm::Stack const&, llvm::Stack const&)::$_28) /home/mskvortsov/tonlabs/TON-Compiler/llvm/include/llvm/ADT/STLExtras.h:915:10
#15 0x00007f0b555da93f llvm::StackFixup::Diff(llvm::Stack const&, llvm::Stack const&) /home/mskvortsov/tonlabs/TON-Compiler/llvm/lib/Target/TVM/TVMStackFixup.cpp:95:3
#16 0x00007f0b555c9e0b llvm::Stack::operator-(llvm::Stack const&) const /home/mskvortsov/tonlabs/TON-Compiler/llvm/lib/Target/TVM/TVMStack.cpp:290:10
#17 0x00007f0b555f815d (anonymous namespace)::TVMStackModel::prepareStackFor(llvm::MachineInstr&, llvm::Stack const&, llvm::SlotIndex, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*) /home/mskvortsov/tonlabs/TON-Compiler/llvm/lib/Target/TVM/TVMStackModel.cpp:570:9
#18 0x00007f0b555f7226 (anonymous namespace)::TVMStackModel::processInstruction(llvm::MachineInstr&, llvm::Stack&) /home/mskvortsov/tonlabs/TON-Compiler/llvm/lib/Target/TVM/TVMStackModel.cpp:267:3
#19 0x00007f0b555f6639 (anonymous namespace)::TVMStackModel::runOnBasicBlocks(llvm::MachineFunction&, llvm::Stack const&) /home/mskvortsov/tonlabs/TON-Compiler/llvm/lib/Target/TVM/TVMStackModel.cpp:294:18
#20 0x00007f0b555f5b82 (anonymous namespace)::TVMStackModel::runOnMachineFunction(llvm::MachineFunction&) /home/mskvortsov/tonlabs/TON-Compiler/llvm/lib/Target/TVM/TVMStackModel.cpp:513:7

Segmentation fault on -O0 compilation

${ZKLLVM_SYSROOT}/bin/clang++ -target tvm --sysroot ${ZKLLVM_SYSROOT} -O0 -DTVM -export-json-abi -o dvm_cpp.abi ../pytest/data/dvm_cpp_multireturn.cpp
${ZKLLVM_SYSROOT}/bin/clang++ -target tvm --sysroot ${ZKLLVM_SYSROOT} -O0 -DTVM -o dvm_cpp.tvc ../pytest/data/dvm_cpp_multireturn.cpp -DBOOST_DISABLE_ASSERTS -DBOOST_EXCEPTION_DISABLE -I${ZKLLVM_SYSROOT}/include/std
PLEASE submit a bug report to https://github.com/tonlabs/TON-Compiler/issues and include the crash backtrace.
Stack dump:
0.	Program arguments: /nix/store/y2kb50jq0h8va1j5n1g7203fd3cwf68d-zkllvm-0.1.0/zkllvm/bin/llc /tmp/nix-shell.YatXg6/dvm_cpp_multireturn-e307b9-optimized-675682.bc -mtriple=tvm -filetype=asm -o /tmp/nix-shell.YatXg6/dvm_cpp_multireturn-e307b9-a05071.s -O0
 #0 0x0000000001431341 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/nix/store/y2kb50jq0h8va1j5n1g7203fd3cwf68d-zkllvm-0.1.0/zkllvm/bin/llc+0x1431341)
 #1 0x000000000142f04e llvm::sys::RunSignalHandlers() (/nix/store/y2kb50jq0h8va1j5n1g7203fd3cwf68d-zkllvm-0.1.0/zkllvm/bin/llc+0x142f04e)
 #2 0x0000000001431876 SignalHandler(int) Signals.cpp:0:0
 #3 0x00007ffff7d09d60 __restore_rt (/nix/store/x33pcmpsiimxhip52mwxbb5y77dhmb21-glibc-2.37-8/lib/libc.so.6+0x38d60)
 #4 0x0000000000c1b51b llvm::TargetPassConfig::addPass(llvm::Pass*, bool) (/nix/store/y2kb50jq0h8va1j5n1g7203fd3cwf68d-zkllvm-0.1.0/zkllvm/bin/llc+0xc1b51b)
 #5 0x0000000000c1d3ee llvm::TargetPassConfig::addRegAssignAndRewriteFast() (/nix/store/y2kb50jq0h8va1j5n1g7203fd3cwf68d-zkllvm-0.1.0/zkllvm/bin/llc+0xc1d3ee)
 #6 0x0000000000c1cb34 llvm::TargetPassConfig::addMachinePasses() (/nix/store/y2kb50jq0h8va1j5n1g7203fd3cwf68d-zkllvm-0.1.0/zkllvm/bin/llc+0xc1cb34)
 #7 0x00000000009ebd63 llvm::LLVMTargetMachine::addPassesToEmitFile(llvm::legacy::PassManagerBase&, llvm::raw_pwrite_stream&, llvm::raw_pwrite_stream*, llvm::CodeGenFileType, bool, llvm::MachineModuleInfoWrapperPass*) (/nix/store/y2kb50jq0h8va1j5n1g7203fd3cwf68d-zkllvm-0.1.0/zkllvm/bin/llc+0x9ebd63)
 #8 0x00000000006c0e18 main (/nix/store/y2kb50jq0h8va1j5n1g7203fd3cwf68d-zkllvm-0.1.0/zkllvm/bin/llc+0x6c0e18)
 #9 0x00007ffff7cf4ace __libc_start_call_main (/nix/store/x33pcmpsiimxhip52mwxbb5y77dhmb21-glibc-2.37-8/lib/libc.so.6+0x23ace)
#10 0x00007ffff7cf4b89 __libc_start_main@GLIBC_2.2.5 (/nix/store/x33pcmpsiimxhip52mwxbb5y77dhmb21-glibc-2.37-8/lib/libc.so.6+0x23b89)
#11 0x00000000006bc5c5 _start (/nix/store/y2kb50jq0h8va1j5n1g7203fd3cwf68d-zkllvm-0.1.0/zkllvm/bin/llc+0x6bc5c5)
clang-14: error: unable to execute command: Segmentation fault (core dumped)
clang-14: error: tvm_linker command failed due to signal (use -v to see invocation)

Suboptimal code generation for if-then-else

int g(int);
int h(int);
int foo(int v) {
  if (v < 0)
    return g(7);
  return h(13);
}

define dso_local i257 @foo(i257 %v) local_unnamed_addr #0 {
entry:
  %cmp = icmp slt i257 %v, 0
  br i1 %cmp, label %if.then, label %if.end

if.then:                                          ; preds = %entry
  %call = tail call i257 @g(i257 7) #2
  br label %return

if.end:                                           ; preds = %entry
  %call1 = tail call i257 @h(i257 13) #2
  br label %return

return:                                           ; preds = %if.end, %if.then
  %retval.0 = phi i257 [ %call, %if.then ], [ %call1, %if.end ]
  ret i257 %retval.0
}

foo:                                    ; @foo
; %bb.0:                                ; %entry
                                        ; { %5 | - }
  PUSHINT 0                       ; >%21 = CONST_I257 i257 0
                                        ; { %5 | %21 | - }
  LESS                            ; >%6 = SLT %5, %21
                                        ; { %6 | - }
  PUSH  c0                      ; >%3 = PUSHC i257 0
                                        ; { %6 | %3 | - }
  PUSHCONT                        ; >%17 = PUSHCONT_MBB %bb.3, 0
                                        ; { %6 | %3 | %17 | - }
  {
; %bb.3:                                ; %return
                                        ; { %3 | %18 | - }
    SWAP                          ; { %18 | %3 | - }
    POP c0                      ; { %18 | - }
                                        ; fallthrough return

  }
  PUSHCONT                        ; >%20 = PUSHCONT_MBB %bb.1, 0
                                        ; { %6 | %3 | %17 | %20 | - }
  {
; %bb.1:                                ; %if.then
                                        ; { %3 | %17 | - }
    PUSHINT 7               ; >%23 = CONST_I257 i257 7
                                        ; { %3 | %17 | %23 | - }
    CALL  $g$                     ; >%18 = CALL_1_INT @g, %23
                                        ; { %3 | %17 | %18 | - }
    SWAP                          ; { %3 | %18 | %17 | - }
    JMPX                          ; { %3 | %18 | %17 | - } => { %3 | %18 | - }
  }
  ROLLREV 2                       ; { %6 | %20 | %3 | %17 | - }
  ROLL  3                       ; { %20 | %3 | %17 | %6 | - }
  ROLL  3                       ; { %3 | %17 | %6 | %20 | - }
  IFJMP                           ; { %3 | %17 | %6 | %20 | - } => { %3 | %17 | - }
; %bb.2:                                ; %if.end
                                        ; { %3 | %17 | - }
  PUSHINT 13                      ; >%22 = CONST_I257 i257 13
                                        ; { %3 | %17 | %22 | - }
  CALL  $h$                     ; >%18 = CALL_1_INT @h, %22
                                        ; { %3 | %17 | %18 | - }
  SWAP                            ; { %3 | %18 | %17 | - }
  JMPX                            ; { %3 | %18 | %17 | - } => { %3 | %18 | - }

An ideal output would be

PUSHINT 0
LESS
PUSHCONT { PUSHINT 13 CALL $h$ }
PUSHCONT { PUSHINT  7 CALL $g$ }
IFELSE

Clang failure on tuple assignment

struct __attribute__((tvm_tuple)) St {
  int value;
  __tvm_slice slice;
};

void foo(__tvm_slice slice, struct St *st)
{
  *st = __builtin_tvm_ldu(slice, 64);
}
test.cc:8:7: error: no viable overloaded '='
  *st = __builtin_tvm_ldu(slice, 64);
  ~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test.cc:1:35: note: candidate function (the implicit copy assignment operator) not viable: no known conversion from '__tvm_literal_struct_WiTs'
      (aka '__tvm_literal_struct_WiTs_Tag') to 'const St' for 1st argument
struct __attribute__((tvm_tuple)) St {
                                  ^
test.cc:1:35: note: candidate function (the implicit move assignment operator) not viable: no known conversion from '__tvm_literal_struct_WiTs'
      (aka '__tvm_literal_struct_WiTs_Tag') to 'St' for 1st argument
struct __attribute__((tvm_tuple)) St {
                                  ^
1 error generated.

Cell underflow error in "Giver" contract example.

Steps to reproduce

  • Clone https://github.com/tonlabs/samples.git
  • Go to "cpp/Giver" example
  • Comment "Giver" part
  • Build sample (see attach)
  • Run test via tvm_linker
  • Error "cell underflow, code 9" will be produced in the method "get_balance". At the point when we try to read uint256 method parameter.

Source code attached:
cell-underflow-issue.tar.gz

Client.hpp

#pragma once
#include <tvm/schema/message.hpp>

namespace tvm::schema {

__interface IClient {
	__attribute__((internal, external)) void constructor() = 1;
	__attribute__((external)) void get_money(uint_t<256> balance) = 2;
};

struct DClient {
	uint_t<1> x;
};

struct EClient {};

} // namespace tvm::schema

Client.cpp

#include "Client.hpp"
#include <tvm/contract.hpp>
#include <tvm/contract_handle.hpp>
#include <tvm/msg_address.inline.hpp>
#include <tvm/replay_attack_protection/timestamp.hpp>
#include <tvm/smart_switcher.hpp>

using namespace tvm::schema;
using namespace tvm;

class Client final : public smart_interface<IClient>, public DClient {
public:
	__always_inline void constructor() final {}
	__always_inline void get_money(uint_t<256> balance) final;
};
DEFINE_JSON_ABI(IClient, DClient, EClient);

void Client::get_money(uint_t<256> balance) {
	require(1234 == balance, 101);
}

DEFAULT_MAIN_ENTRY_FUNCTIONS(Client, IClient, DClient, 1800)

Build

$ clang++ -target tvm --sysroot=$TVM_INCLUDE_PATH -export-json-abi -o Client.abi Client.cpp
$ export ADDRESS=f2aa8444870a6f8515c2673e7cf90a7af927787c9651b0ee196c0daa73e39304
$ tvm-build++.py -o $ADDRESS.tvc --abi Client.abi Client.cpp --include $TVM_INCLUDE_PATH --linkerflags="--genkey /tmp/testkeyfile"
$ tvm_linker test $ADDRESS --abi-json Client.abi --abi-method constructor --abi-params '{}' --sign /tmp/testkeyfile
$ tvm_linker test $ADDRESS --abi-json Client.abi --abi-method get_money --abi-params '{"balance":1234}' --sign /tmp/testkeyfile

Output

Error will be produced: cell underflow, code 9

TVM linker 0.1.0
COMMIT_ID: d84a6adfe6802553fe30bd18535172596ec61a06
BUILD_DATE: 2021-02-09 12:02:41 +0300
COMMIT_DATE: 2021-01-27 18:36:24 +0300
GIT_BRANCH: master
TEST STARTED
body = ...
Unhandled exception: cell underflow, code 9, value: 0
TVM terminated with exit code 9
Gas used: 3896

Build failed 🤷🥺

build.log

Reproduction:

FROM ubuntu
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get -qqy update
RUN apt-get -qqy install cmake ninja-build g++ git python curl zlib1g
RUN git clone --depth 1 https://github.com/tonlabs/ton-compiler.git /usr/src/ton-compiler
RUN mkdir /usr/src/ton-compiler/build
WORKDIR /usr/src/ton-compiler/build

RUN cmake \
    -G Ninja \
    -DLLVM_ENABLE_ASSERTIONS=1 \
    -DCMAKE_BUILD_TYPE="Release" \
    -DLLVM_BUILD_LLVM_DYLIB=1 \
    -DLLVM_LINK_LLVM_DYLIB=1 \
    -DLLVM_TARGETS_TO_BUILD="" \
    -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD="TVM" \
    -DLLVM_BYTE_SIZE_IN_BITS=257 \
    -DLLVM_USE_LINKER=gold \
    ../llvm
RUN ninja

Stack permutation inefficiency

void foo(int, int, int, int, int, int, int, int,
         int, int, int, int, int, int, int, int,
         int);
void puxc2(int vf, int ve, int vd, int vc, int vb, int va, int v9, int v8,
           int v7, int v6, int v5, int v4, int v3, int v2, int v1, int v0) {
  foo(vf, ve, vd, vc, vb, va, v1, v0, v7, v6, v5, v4, v3, v2, v7, v8, v9);
}

  ROLL  15
  ROLL  15
  ROLL  15
  ROLL  15
  ROLL  15
  ROLL  15
  ROLL  7
  ROLL  7
  ROLL  13
  ROLL  13
  ROLL  13
  ROLL  13
  ROLL  13
  ROLL  13
  PUSH  s5
  ROLL  15
  ROLL  16
  CALL  $foo$

Wanted:

PUXC2 s7, s8, s9
CALL $foo$

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.