第1章:玩转LLVM

LLVM 编译器学习笔记之二十七 -- EarlyCSE, PRE, LICM, hoist, Sink 1、__attribute__((__aligned__)) 的正确使用方法,参考https://stackoverflow.com/questions/10951039/specifying-64-bit-alignment,注意并不是写在结构体定义的上一行 struct foo { int a, b, c; } __attribute__((__aligned__(8))); // aligned to 8-byte (64-bit) boundary ......... 阅读详情

LLVM编译器基础设施项目始于2000年伊利诺伊大学,最初是一个研究项目,旨在为各种静态和动态编程语言提供基于SSA(静态单赋值)的现代编译技术。如今,它已发展成为一个包含许多子项目的综合项目,提供一系列具有明确定义接口的可重用库。

LLVM是用C++实现的,其核心是它提供的LLVM核心库。这些库为我们提供了opt工具,即目标独立的优化器,以及对各种目标架构的代码生成支持。还有其他一些工具使用核心库,但本书的主要焦点将与上述三个相关。这些工具是围绕LLVM中间表示(LLVM IR)构建的,几乎可以映射所有高级语言。因此,基本上,要使用LLVM的优化器和代码生成技术为某种编程语言编写的代码,我们所需要做的就是为该语言编写一个前端,将高级语言转换为LLVM IR。已经有许多针对C、C++、Go、Python等语言的前端。本章将涵盖以下主题:

  • 模块化设计和库的集合
  • 熟悉LLVM IR
  • LLVM工具及其在命令行的使用

模块化设计和库的集合


LLVM最重要的特点是它被设计成一系列的库。让我们通过LLVM优化器opt的例子来理解这一点。优化器可以运行许多不同的优化过程。每个过程都写成了一个从LLVM的Pass类派生的C++类。每个写好的过程都可以编译成一个**.o文件,然后被存档成一个.a**库。这个库将包含opt工具的所有过程。库中的所有过程都是松散耦合的,即它们明确地指明了对其他过程的依赖。

当优化器运行时,LLVM的PassManager使用明确提及的依赖信息以最优方式运行过程。基于库的设计允许实现者选择执行过程的顺序,也可以根据需求选择要执行的过程。只有需要的过程才会链接到最终应用程序,而不是整个优化器。

下图展示了如何将每个过程链接到特定库中的特定对象文件。在下图中,PassA引用LLVMPasses.a中的PassA.o,而自定义过程则引用另一个库MyPasses.a中的MyPass.o对象文件。

img

代码生成器也像优化器一样,利用了这种模块化设计,将代码生成分解为若干个独立的过程,包括指令选择、寄存器分配、调度、代码布局优化和汇编代码生成。

在上述的每个阶段中,几乎每个目标都有一些共通之处,例如为虚拟寄存器分配可用的物理寄存器的算法,尽管不同目标的寄存器集合各不相同。因此,编译器的编写者可以修改上述的每个过程,并创建定制的针对特定目标的过程。使用 tablegen 工具和针对特定架构的表描述 .td 文件,可以帮助实现这一点。我们将在本书后面讨论这是如何实现的。

由此产生的另一个能力是,能够轻松地将一个错误定位到优化器中的特定过程。一个名为 Bugpoint 的工具利用了这一能力,可以自动缩减测试用例,并定位出导致错误的过程。

了解LLVM IR


LLVM的中间表示(IR)是LLVM项目的核心。通常,每个编译器都会生成一个中间表示,然后在其上运行大部分优化。对于面向多源语言和不同架构的编译器,在选择IR时的一个重要决策是,它既不应是非常高级的,即与源语言紧密相连,也不应是非常低级的,即接近于目标机器指令。LLVM IR旨在成为一种通用的IR,通过处于足够低的级别,以便高级思想可以清晰地映射到它上。理想情况下,LLVM IR应该是与目标无关的,但由于某些编程语言本身的固有目标依赖性,它并非如此。例如,在Linux系统中使用标准C头文件时,头文件本身是目标依赖的,它可能为实体指定特定类型,以便与特定目标架构的系统调用匹配。

大多数LLVM工具都围绕这个中间表示旋转。不同语言的前端从高级源语言生成这个IR。LLVM的优化器工具在这个生成的IR上运行,以优化代码,提高性能,代码生成器使用这个IR进行针对特定目标的代码生成。这个IR有三种等效形式:

  • 内存中的编译器IR
  • 磁盘上的位码表示
  • 人类可读形式(LLVM汇编)

现在我们来看一个例子,了解LLVM IR是什么样子的。我们将采用一小段C代码,并使用clang将其转换为LLVM IR,尝试通过将其映射回源语言来理解LLVM IR的细节。

$ cat add.c
int globvar = 12;

int add(int a) {
return globvar + a;
}

使用以下选项的clang前端将其转换为LLVM IR:

$ clang -emit-llvm -c -S add.c
$ cat add.ll
; ModuleID = 'add.c'
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

@globvar = global i32 12, align 4

; Function Attrs: nounwind uwtable
define i32 @add(i32 %a) #0 {
  %1 = alloca i32, align 4
  store i32 %a, i32* %1, align 4
  %2 = load i32, i32* @globvar, align 4
  %3 = load i32, i32* %1, align 4
  %4 = add nsw i32 %2, %3
  ret i32 %4
}

attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "unsafe-fp-math"="false" "use-soft-float"="false" }

!llvm.ident = !{!0}
CopyExplain

现在,让我们看一下生成的IR,并了解它的全部内容。您可以看到第一行给出了ModuleID,它定义了add.c文件的LLVM模块。一个LLVM模块是一个顶级数据结构,包含了输入LLVM文件的全部内容。它由函数、全局变量、外部函数原型和符号表条目组成。

接下来的几行显示了目标数据布局和目标三元组,从中我们可以知道目标是运行在Linux上的x86_64处理器。datalayout字符串告诉我们机器的字节序(‘e’表示小端序),以及名称改编方式(m : e表示elf类型)。每个规格由’-'分隔,每个后续规格提供关于该类型及其大小的信息。例如,i64:64表示64位整数是64位的。

然后,我们有一个全局变量globvar。在LLVM IR中,所有全局变量以’@‘开头,所有局部变量以’%'开头。变量使用这些符号作为前缀的两个主要原因是:第一个原因是,编译器不必担心与保留字发生命名冲突;第二个原因是,编译器可以快速地为变量生成一个临时名称,而不必担心与符号表发生冲突。这第二个属性对于在静态单赋值(SSA)形式中表示IR很有用,在SSA形式中,每个变量只被赋值一次,而且每个变量的使用都在其定义之前。因此,在将常规程序转换为SSA形式时,我们会为变量的每次重新定义创建一个新的临时名称,并将早期定义的范围限制在此重新定义之前。

LLVM将全局变量视为指针,因此需要使用load指令显式地解引用全局变量。同样,要存储一个值,需要一个显式的store指令。

局部变量有两类:

  • 寄存器分配的局部变量:这些是临时的和分配的虚拟寄存器。在代码生成阶段,虚拟寄存器被分配给物理寄存器,我们将在本书的后面章节中看到。它们是通过为变量使用新符号创建的,例如:

    %1 = some value
    
  • 栈分配的局部变量:这些是通过使用alloca指令,在当前执行函数的栈帧上分配变量来创建的。alloca指令提供了一个指向分配类型的指针,需要显式使用load和store指令来访问和存储值。

    %2 = alloca i32
    

现在,让我们看看add函数在LLVM IR中是如何表示的。define i32 @add(i32 %a)与C中的函数声明非常相似。它指定函数返回整数类型i32并接受一个整数参数。此外,函数名称前有’@',表示它具有全局可见性。

函数内部是实际的功能处理。这里需要注意的一些重要事项是,LLVM使用三地址指令,即一个数据处理指令,它有两个源操作数,并将结果放在单独的目标操作数中(%4 = add i32 %2, %3)。此外,代码是SSA形式的,即IR中的每个值都有一个定义该值的单一赋值。这对许多优化非常有用。

在生成的IR中紧随其后的属性字符串指定了函数属性,这与C++属性非常相似。这些属性是为已定义的函数所设。在LLVM IR中,为每个定义的函数都定义了一组属性。

属性之后的代码是用于ident指令的,用于识别模块和编译器版本。

  • LLVM工具及其在命令行中的使用


    到目前为止,我们已经了解了LLVM IR(人类可读形式)是什么,以及如何用它来表示高级语言。现在,我们将看一看LLVM提供的一些工具,这些工具可以让我们将这个IR转换成其他格式,然后再转换回原始形式。让我们逐一看一下这些工具及其示例。

    • llvm-as:这是LLVM汇编器,它接受LLVM IR的汇编形式(人类可读)并将其转换为位码格式。使用前面的add.ll作为例子,将其转换为位码。要了解更多关于LLVM Bitcode文件格式,请参阅

      $ llvm-as add.ll –o add.bc
      

      要查看这个位码文件的内容,可以使用诸如hexdump之类的工具。

      $ hexdump –c add.bc
      
    • llvm-dis:这是LLVM反汇编器。它接受位码文件作为输入,并输出LLVM汇编。

      $ llvm-dis add.bc –o add.ll
      

      如果您检查add.ll并与之前的版本进行比较,它将与之前的版本相同。

    • llvm-link:llvm-link链接两个或多个llvm位码文件,并输出一个llvm位码文件。为了查看演示,请编写一个调用add.c文件中函数的main.c文件。

      $ cat main.c
      #include<stdio.h>
      
      extern int add(int);
      
      int main() {
      int a = add(2);
      printf("%d\n",a);
      return 0;
      }
      

      使用以下命令将C源代码转换为LLVM位码格式。

      $ clang -emit-llvm -c main.c
      

      现在链接main.bc和add.bc以生成output.bc。

      $ llvm-link main.bc add.bc -o output.bc
      
    • lli:lli直接使用即时编译器或解释器(如果当前架构有)执行LLVM位码格式的程序。lli不像虚拟机,无法执行不同架构的IR,只能解释主机架构的IR。使用由llvm-link生成的位码格式文件作为lli的输入。它将在标准输出上显示输出。

      $ lli output.bc
      14
      
    • llc:llc是静态编译器。它将LLVM输入(汇编形式/位码形式)编译成指定架构的汇编语言。在以下示例中,它接受由llvm-link生成的output.bc文件,并生成汇编文件output.s。

      $ llc output.bc –o output.s
      

      让我们看一下output.s汇编的内容,特别是生成代码的两个函数,这与本地汇编器生成的内容非常相似。

    Function main:
      .type  main,@function
    main:                                   # @main
      .cfi_startproc
    # BB#0:
      pushq  %rbp
    .Ltmp0:
      .cfi_def_cfa_offset 16
    .Ltmp1:
      .cfi_offset %rbp, -16
      movq  %rsp, %rbp
    .Ltmp2:
      .cfi_def_cfa_register %rbp
      subq  $16, %rsp
      movl  $0, -4(%rbp)
      movl  $2, %edi
      callq  add
      movl  %eax, %ecx
      movl  %ecx, -8(%rbp)
      movl  $.L.str, %edi
      xorl  %eax, %eax
      movl  %ecx, %esi
      callq  printf
      xorl  %eax, %eax
      addq  $16, %rsp
      popq  %rbp
      retq
    .Lfunc_end0:
    
    
    Function: add
    add:                                    # @add
      .cfi_startproc
    # BB#0:
      pushq  %rbp
    .Ltmp3:
      .cfi_def_cfa_offset 16
    .Ltmp4:
      .cfi_offset %rbp, -16
      movq  %rsp, %rbp
    .Ltmp5:
      .cfi_def_cfa_register %rbp
      movl  %edi, -4(%rbp)
      addl  globvar(%rip), %edi
      movl  %edi, %eax
      popq  %rbp
      retq
    .Lfunc_end1:CopyExplain
    
    • opt:这是模块化的LLVM分析器和优化器。它接受输入文件并根据命令行指定的选项执行优化或分析。它执行分析器还是优化器取决于命令行选项。

      opt [options] [input file name]
      

      当提供了--analyze选项时,它对输入执行各种分析。已经提供了一组可以通过命令行指定的分析选项,或者可以编写自己的分析通道并提供给该分析通道的库。一些有用的分析通道,可以使用以下命令行参数指定:

      • basicaa:基本别名分析
      • da:依赖性分析
      • instcount:计算各种指令类型
      • loops:有关循环的信息
      • scalar evolution:标量演化分析

      当没有传递--analyze选项时,opt工具执行实际的优化工作,并尝试根据传递的命令行选项优化代码。与前面的情况类似,您可以使用一些已有的优化通道,或为优化编写自己的通道。一些有用的优化通道,可以使用以下命令行参数指定:

      • constprop:简单的常量传播
      • dce:死代码消除通道
      • globalopt:全局变量优化通道
      • inline:函数内联通道
      • instcombine:组合冗余指令
      • licm:循环不变代码移动
      • tailcallelim:尾调用消除

注意

在继续之前,我们必须注意本章中提到的所有工具都是为编译器编写者准备的。最终用户可以直接使用clang来编译C代码,而无需将C代码转换为中间表示

总结


在本章中,我们探讨了LLVM的模块化设计:如何在LLVM的opt工具中使用它,以及它如何适用于LLVM核心库。然后我们研究了LLVM的中间表示,以及一个语言的各种实体(变量、函数等)如何映射到LLVM IR。在最后一节中,我们讨论了一些重要的LLVM工具,以及它们如何用于将LLVM IR从一种形式转换为另一种形式。

在下一章中,我们将看到如何编写一个可以输出LLVM IR的语言前端,使用LLVM机制。

LLVM的编译链工具 通常我们在命令行上调用的clang工具,是Clang驱动程序,因为LLVM本质上只是一个编译器框架,所以需要一个驱动程序把整个编译器的功能串起来,clang能够监控整个编译器的流程,即能够调用到Clang和LLVM的各种库,最终实现编译的功能。来指定输出是汇编文件还是目标文件,若生成是目标文件,llc会调用LLVM中的汇编输出的代码库来工作(注意这个汇编器和gcc的汇编器也不同,它输入的是MI,是一种后端的中间表示)。clang能够调用起来整个编译器的流程,也就是上边其他工具调用的库,它很多都同样会调用。 阅读详情

相关推荐

LLVM系列第一章:编译LLVM源码

详细介绍如何利用CMake和Ninja工具来编译及安装LLVM。

Zhanglin_Wu的专栏, C++, Scrum, LLVM, 编译器 1万+

LLVM IR(一)——如何使用LLVM编译执行代码

可以转载,请注明出处! 在阅读这一章节之前,需要本地安装llvm环境,没安装点这里:https://blog.youkuaiyun.com/qq_42570601/article/details/107146407 1.1 LLVM IR的三种结构 LLVM的代码有3种表示形式:内存编译器中的IR(用户不可知)、存于磁盘的 bitcode(二进制文件),以及用户可读的汇编码。我们接下来要介绍的就是用户可读的汇编码。 1.2将C转为LLVM IR汇编码 1> 首先在tpy.c文件中编写一段c源码: #inclu.

yelvens的博客 1万+

第1章:构建LLVM时节约资源

LLVM是许多令人惊叹的工业和学术项目所采用的最先进的编译器优化和代码生成框架,例如JavaScript引擎中的)编译器和)框架。它是构建编程语言和二进制文件工具的有用工具箱。然而,尽管该项目具有强大的稳健性,但其学习资源分散,文档也不是最佳的。因此,即使是对LLVM有一定经验的开发者,其学习曲线也相当陡峭。本书旨在通过以实用的方式为您提供LLVM中常见和重要领域的知识来解决这些问题——向您展示一些有用的工程技巧,指出鲜为人知但方便的功能,并举例说明。作为一名。

cppclub的博客 1456

LLVM别名分析框架

介绍 别名分析(又名指针分析,是指针分析的一种)是一类技术,试图确定两个指针是否可以指向内存中的同一对象。别名分析有许多不同的算法和分类方法:流敏感vs.流不敏感、上下文敏感vs.上下文不敏感、字段敏感vs.字段不敏感、基于统一vs.基于子集等。传统上,别名分析用Must、May或No别名response响应查询,表示两个指针总是指向同一个对象,可能指向同一个对象,或者已知永远不会指向同一个对象。 LLVM AliasAnalysis类是LLVM系统中客户使用和别名分析实现的主要接口。这个类是别名分析信息的

m0_46220969的博客 1728

【LLVM奶妈式教学-1】LLVM从安装到手写第一个pass 【hello llvm】

奶妈式LLVM安装+编译+第一个PASS教学【hello llvm】

qq_41645482的博客 3121

LLVM系列:1.设计思想和LLVM IR简介

本文简单介绍了LLVM项目的背景,并针对LLVM中优化器和代码生成器的模块化设计思想进行了介绍,也简单介绍了LLVM IR的特点,包括结构、变量类型、指令格式等。

你的深度学习小站 2204

LLVM 命令指南

以下文档是所有 LLVM 工具的命令描述。这些页面描述了如何使用 LLVM 命令及其选项。注意,这些页面并没有描述所有工具可用的所有选项。要获得完整的清单,请将 --help (通用选项)或 --help-hidden (通用选项和调试选项)参数传递给您感兴趣的工具。 1. 基本命令 llvm-as —— LLVM汇编器 llvm-dis —— LLVM反汇编器 opt —— LLVM优化器 l...

梦在哪里的博客 7099

LLVM代码研读(3) --- LLVM后端(1): 概述

前言:因为LLVM的后端是相对最为复杂的部分:国内的编译原理的教课书多重点会在前端上,同时因为后端多会与实际系统相关,会涉及编译器的IR指令和实际平台的特性,繁琐又相对枯燥。该部分是后端的基础,稍后会涉及到实际平台。

码农驿站 4960

第 1 章:安装 LLVM

CMake系统使用文件中的项目描述。顶层文件位于llvm目录,。其他目录也有文件,在生成过程中会递归包含。基于项目描述中提供的信息,CMake检查安装的编译器,检测库和符号,并创建构建系统文件,例如或Makefile(取决于所选择的生成器)。还可以定义可重用模块,例如用于检测是否安装了LLVM的函数。这些脚本放置在特殊的cmake目录(llvm/cmake)中,在生成过程中自动搜索。可以通过定义CMake变量来自定义构建过程。命令行选项-D用于将变量设置为一个值。CMake脚本中使用这些变量。

cppclub的博客 4192

play_with_llvm:关于LLVM和Clang的书(中文开源书:玩转LLVM)

play_with_llvm:关于LLVM和Clang的书(中文开源书:玩转LLVM)

第2章:探索LLVM的构建系统特性

本章深入探讨了LLVM的CMake构建系统。我们看到了如何使用LLVM自己的CMake指令编写简洁有效的构建脚本,无论是对于树内还是树外开发。学习这些CMake技能可以使您的LLVM开发更高效,并为您提供更多选项,以便将LLVM功能与其他现有代码库或自定义逻辑结合使用。在下一章中,我们将介绍LLVM项目中另一个重要的基础设施,称为LLVM LIT,这是一个易于使用但通用的框架,用于运行各种测试。

cppclub的博客 1426

别再手动算LLC了!用Mathcad 15分钟搞定谐振参数与增益曲线(附已验证产品案例)

本文详细介绍了如何利用Mathcad在15分钟内高效完成LLC谐振变换器的参数计算与增益曲线绘制。通过对比传统工具,突出Mathcad在自然数学表达、实时单位换算和动态参数关联方面的独特优势,帮助电源工程师大幅提升设计效率。文章还提供了已验证的产品案例和实用模板,助力工程师快速掌握谐振参数优化技巧。

weixin_42548888的博客 546

LLVM入门-章1

编译器LLVM入门

TomOfJerry的博客 706

UDS服务应该支持哪些否定响应码

UDS服务应该支持哪些否定响应码所有服务都需支持的否定响应码具体的服务需要支持的否定响应码否定响应码定义及其取值 USD诊断服务的否定响应中包含有导致否定响应原因的编码,称为否定响应码(NRC, Negative Response Code)。否定响应码的取值范围为0x00 - 0xFF,被分为三组: 0x00:服务器内部实现否定响应码判断逻辑时使用,表示要给出肯定响应。 0x01 – 0x7F:诊断通信相关的否定响应码。 0x80 – 0xFF:服务器收到诊断服务请求时,由于某些条件不满足要求而给出的否定

闲聊汽车软件开发 4万+

matlab tolx,Nelder-Mead算法matlab

Nelder-Mead算法适合变量数不是很多的方程求极值.原理:Nelder-Mead法是利用多面体来逐步逼近最佳点x*.设函数变量为n维,则在n维空间里多面体有(n+1)个顶点.设x1,x2,...,xn+1为多面体的顶点,且满足:f(x1)<=f(x2)<=...<=f(xn+1)Nelder-Mead法试着将多面体中最差的顶点xn+1(也就是函数的最大点)以新的最佳点替代,...

weixin_36485298的博客 1480

Ubuntu 18.04 LTS 安装 LLVM 12.0.1

Ubuntu 18.04 LTS 安装 LLVM 12.0.1

weixin_44200757的博客 1万+

【人工智能论文发表】基于医学病例文本和多模态大模型的医疗影像分割方法研究

摘要:本研究提出MMS-Former,一种基于级联多模态Transformer的文本引导医学图像分割框架。该模型创新性地将临床文本信息深度融入图像分割全过程,通过SwinUNETR提取视觉特征,ClinicalBERT编码病历文本,并在解码器的每个上采样阶段通过交叉注意力模块实现多级文本特征融合。实验表明,相比纯视觉模型,MMS-Former在Dice系数和IoU指标上分别提升3%以上,在处理边界模糊目标时表现尤为突出。模型还设计了结合Dice损失和图文对比损失的复合目标函数,确保分割精度与语义对齐。代码实

u012133341的博客 141

LLVM:How 在 Windows 上使用 LLVM Pass

Evently,我来到了这一步,which I can 决定使用 what’s like 环境。Before 由于项目需要学习了如何利用来处理源码进行混淆操作,但对于环境的配置却不知道如何进行。那么这篇就是对于。之前我看了前人的智慧,就承接了这套环境进行了代码设计。但里面有些内容让我感觉在上感觉很不方便,所以 want 探索新的环境搭建方式,时隔 1 年我终于开始了。使用时遇到重大困难,还好有这位前人的智慧。这种不方便是由于使用的是标准,而非,使得你编译出来的代码找不到动态链接库,需要自带。

fishwheel的博客 1307

SimpleITK使用——1. 进行Resample/Resize操作

文章目录1. 变换到一个新的spacing1.1 使用Resample()的方法1.1.1 完整代码1.1.2 转换前后图像1.2 使用ResampleImageFilter()的方法2. 已知原图和变换后目标图像的大小2.1 代码2.2 转换后图像3. 相关内容说明3.0 体素和spacing3.1 Resample() 函数说明3.2 itk::simple::ResampleImageFilter函数说明 1. 变换到一个新的spacing 1.1 使用Resample()的方法 1.1.1

啷个哩个啷 8079

损失函数大汇总(五十九)(TopoInteraction Loss附公式推导与代码)

本文介绍了TopoInteraction Loss,一种用于多类别分割任务的拓扑交互约束损失函数。不同于传统拓扑损失关注单类别的连通性和孔洞数量,该损失重点约束不同类别之间的空间关系,包括互斥(exclusion)和包含(containment)两种典型拓扑关系。通过将全局拓扑约束转化为局部邻接检测,该损失能准确定位破坏预设拓扑关系的像素,并针对性施加惩罚。关键创新点在于:1)将包含关系转化为互斥约束;2)使用卷积运算高效检测非法邻接;3)仅对违规像素施加损失。实验表明,该方法能有效纠正类别间的错误接触,特

悦学共鸣,温柔以待,汇聚光芒,共同成长 350

LLVM系列文章1: Debian/Ubuntu 安装和使用 LLVM

Debian/Ubuntu 安装 LLVM

个人博客 4775

PCL 八叉树的使用

八叉树(Octree)是一种空间划分的数据结构,广泛应用于三维点云的处理和分析。八叉树通过将空间递归地划分为八个子区域,可以有效地组织和索引三维点数据,提升点云的查询、降采样和配准等操作的效率。

纵马踏花向自由 1658

使用 CMake 构建 LLVM

使用 CMake 构建 LLVM1. 介绍2. 快速开始3. 基本的 CMake 用法4. 选项和变量4.1 经常使用的 CMake 变量4.2 特定于LLVM的变量5. CMake Caches6. 执行测试7. 交叉编译8. 在项目中嵌入 LLVM8.1 从源代码开发 LLVM passes9. 特定于编译器/平台的话题9.1 微软Visual c++ 本文为译文,点击此处查看原文。 1. 介...

梦在哪里的博客 1万+

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

LLVM 核心类简明示例

《带有LLVM的eBPF组件》 《The LLVM Compiler Infrastructure | LLVM编译器基础设施》 《LLVM每日谈 | 知乎》 《LLVM 核心类简明示例》 目录 LLVM 核心类简明示例 : llvm::Value && llvm::Type && llvm::Constant llvm::Value llvm:Type llvm::Constant LLVM 核心类简明示例 : llvm::Value &&a.

RToax 1531

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

[llvm cookbook] 1、LLVM设计与使用

了解如何把C语言代码编译为LLVM IR(Intermediate representation)及其他多种形式。与其他编译器(如 GNU Compiler Collection) 不同,LLVM 设计目标是成为一系列的库。

hzq_blog 778

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

上一篇: 第 1 章:模板简介
下一篇: 第1章:构建LLVM时节约资源
段舸
博客等级 码龄3年 533粉丝 32原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值