跳到内容

惯用光/密耳tools

存储库文件导航

MIL工具,一种Monadic中间语言

此存储库中的Java代码实现了一组用于使用MIL程序,包括从中生成MIL的代码LC或MIL源文件,优化MIL代码,翻译MILLLVM。

这些工具主要用作Habit的alb编译器。(请参阅https://github.com/atbit-lang/alb.)然而,它们也可以独立使用,如下面描述的示例。

有关MIL的更多详细信息,请访问https://web.cecs.pdx.edu/~mpj/pubs/mil.html.

mil-tools测试套件的第一次切割可用https://github.com/zipwith/mil测试仪.

致谢:

2014-2018年期间的军事行动工作得到了支持部分资金来自国家科学基金会编号:CNS-1422979。

要求:

使用此存储库中的代码需要以下项目:

  • Java开发工具包(版本>=1.8就足够了)

  • Apache Ant(版本>=1.9.2就足够了)

  • LLVM编译器基础结构(版本>=4.0就足够了)

安装:

首先,我们需要建立多功能平台,并以最简单的方式这样做(假设您已经有一个合适的JDK和Apache Ant已安装)使用以下命令序列:

#确保起点清洁:蚂蚁清洁剂#构建多功能平台:蚂蚁

[使用蚂蚁清洁建议每次更新后使用,以确保一致的构建。]

接下来,复制密尔克shell脚本(或米尔克巴特上的文件Windows),然后编辑文件,以便它包含指向mil-tools.jar公司文件。完成这些步骤后,您应该能够跑步密尔克(无参数)在任何目录中生成如下开始的输出(自己运行命令查看完整列表密尔克选项):

百万美元用法:milc[inputs | options]inputs:filename.milc从指定文件加载选项filename.mil从指定文件加载mil源(.lmil表示文字)filename.lc从指定文件加载lc源(.llc表示文字)选项:-v verbose on-d显示调试消息-ipathlist将项目附加到输入搜索路径...$

使用mil-tools:一个小例子

编译LC源文件的过程(在本例中,演示/fib.lc)到MIL,然后生成LLVM,如下所示以下命令(这次假设您有一个LLVM的适当安装):

#使用mil工具将fib.lc编译为LLVM:milc-ilib--独立演示/fib.lc-ltmp/fib.ll#从生成的LLVM代码生成可执行文件:clang-o tmp/fib tmp/fib.ll演示/运行时。c(c)

密尔克此处使用的命令行选项:

  • -免疫球蛋白设置输入文件的路径以包含自由目录,这是默认的前奏曲.lc和其他存储库文件。

  • --独立的配置密尔克生成一个名为主要的.

  • 演示/fib.lc指定LC源程序的名称。

  • -ltmp/光纤.ll表示密尔克应生成LLVM并在文件中写入代码副本tmp/fib.ll型.

以及对叮当作响命令行选项:

  • -o tmp/fib设置名称(小谎)和文件夹位置(临时管理计划)可执行程序的叮当作响生产。

  • tmp/fib.ll型指定输入LLVM代码的名称;属于当然,这是由前进密尔克命令。

  • 演示/运行时。c(c)是一个小型C源文件的名称提供了打印Word功能,即在原文中使用fib.抄送程序。其他一些示例在单个程序中结合LC和C代码的在本文档中。

取决于LLVM安装/平台的详细信息(对于例如,在macOS上),您可能需要替换海湾合作委员会对于叮当作响在这里的第二个命令中。您可能还需要替换java-jar mil-tools.jar代替密尔克,取决于您的平台(Windows用户可以替换米尔克巴特).

编译生成的LLVM代码的其他方法可能很有用在其他设置中。例如,您可以使用以下两个要编译的命令fib.第1页通过具有特定目标的程序集体系结构(在本例中为32位x86):

#编译生成的LLVM代码:llc-O2-filetype=asm-march=x86 tmp/fib.ll#生成包含生成代码的可执行文件:gcc-m32-o tmp/fib-Wl,-no_pie demo/runtime.c tmp/fib。

您可能会看到表单中的消息警告:使用…覆盖模块目标三元组。。。当您运行上述命令时;我们将需要改进LLVM代码生成器以避免将来出现这种情况释放,但您现在应该可以忽略此消息。

最后,您可以运行编译的程序:

#运行生成的可执行文件:tmp/fib

结果应该如下所示,带有一对任意选择的数字包围着两个144,其中使用两种略有不同的定义进行计算Fibonnacci函数:

9114414417

或者,您可以使用以下命令行运行程序直接通过字节码解释器:

milc-ilib--独立-x演示/fib.lc

更换-x个具有-米查看生成的MIL代码,或使用-我查看生成的LLVM代码等(或者只运行其中之一密尔克,密耳蝙蝠java-jar mil-tools.jar有关其他内容的摘要命令行选项。)

一个更大的例子:优先级集案例研究

作为一个稍大且更复杂的图案示例如上所述演示文件夹还包括一对源基于优先权集案例研究的文件,该案例研究出现在习惯语言报告:

  • prioset.lc公司是优先级集的LC实现(最大值堆)数据结构,基于Habit报告中的代码。(进行了一些更改,以包括此程序中basic所需的外部原语算术和从内存中读/写等操作。如果我们从一个习惯源程序开始,这些详细信息将由Habit编译器自动生成。)

  • 普里奥德莫。c(c)是一个简单的C演示程序,它使用函数来自prioset.lc公司作为一个简单的库。

以下命令可用于编译和运行演示程序(在运行macOS High Sierra的机器上;其他平台需要进行一些更改):

#编译prioset.lc实现:milc-ilib demo/prioset.lc--llvm-main=initPrioset-ltmp/prioset.ll--目标=x86_64-apple-macosx10.13.0--64#编译priodemo.c文件并与prioset.lc中的代码链接:clang-DWORD64-o tmp/priodemo演示/priodemo.c tmp/prioset.ll#运行生成的可执行文件:tmp/priodemo

以下注释解释了所使用的一些命令行选项这里还没有针对前面的示例进行记录:

  • --llvm-main=initPrioset指定的名称必须用于初始化使用其他函数之前的优先级设置数据结构定义于prioset.lc公司.名称initPrioset(初始优先级)用于普里奥德莫。c(c),因此必须指定相同的名称在这里。(关于--llvm-main=。。。命令行选项将在本文档后面介绍。)

  • --目标=x86_64-apple-macosx10.13.0指定“目标生成的LLVM代码中包含的triple”字符串指定目标平台的详细信息;很明显,会的如果使用不同的平台。注意,您可以找到目标三元组用于通过运行命令配置LLVM的llvm-config—主机目标,但单个LLVM安装可以通常可以容纳多种目标类型。

  • --64指定生成的LLVM代码将生成代码假设单词LC中的类型为64位宽。这个-DWORD64码中的选项叮当作响命令行用于确保代码在普里奥德莫。c(c)以相应的方式配置(尤其是通过使用C长的类型作为的表示形式单词值)。或者,也可以通过使用生成程序的32位版本:--32的选项密尔克; -DWORD32型的选项叮当作响; 和一个修改过的的版本--目标=。。。选项,例如更换x86_64码具有i386型.重要提示:相同的单词大小至关重要一致地用于所有使用的LC和C代码片段在一个单独的程序中。未能满足此要求需求可能会导致分割、保护或尝试生成和运行普里奥德莫例子。

此序列中的最终命令产生的输出如下:

$tmp/priodemo优先级设置演示插入一些数字:插入12插入5插入7插入128插入67删除三个数字:删除128拆卸67拆卸12添加更多数字:插入3插入32插入10排空队列:拆卸32拆卸10拆卸7拆卸5拆卸3完成!$

参观密尔沃基的一些工具

mil工具使用一系列编译“通行证”进行处理并转换输入程序。具体的传递顺序用于给定任务的类型取决于输出的类型是必需的:如果用户使用-我例如,flag,然后mil-tools使用额外的通行证如果用户刚刚使用这个-米命令行选项。

但是,出于调试目的,并帮助高级用户了解编译过程的工作原理,可以覆盖默认值并指定自定义的解析序列使用-第页命令行选项。我们将在下面的一系列示例演示了一些关键点mil-tool提供的通行证。示例程序我们在这些演示中使用的是一个名为演示/ex.lc其内容如下:

要求“序言.lc”data Dup a=重复a a入口点swap7::重复(Bit 7)->重复(Bit7)入口点swap8::重复(Bit 8)->重复(Bit8)swap7=交换swap8=交换掉期d=重复x y的情况d->重复y x入口点d1d1=Dup B001 B110

如果您只想加载多线程工具,请检查并编译这个程序设置为MIL时,可以使用命令行选项-第页,如中所示milc-ilib-m演示/ex.lc-p然而,这将产生相当多的输出,并且我们可以通过运行MIL来简化代码优化器。这可以通过添加字符来完成o(o)结束-第页命令行选项,生成以下输出(更一般地说-第页选项包含一系列字母指定特定通道;mil工具将尝试运行正是加载的MIL代码上的传递序列直接或通过编译LC源文件生成):

$milc-ilib-m演示/ex.lc-po数据->(a::*)(b::*=函数([a]->>[b])数据重复(a::*)=重复-------------------------------------------非递归入口点d1::重复(位3)第1天<-Dup(B001、B110)-------------------------------------------非递归b84::针对所有(a::*)。[Dup a]>>=[Dup a]b84【t0】=断言t0重复t1<-重复0 t0t2<-重复1 t0重复(t2,t1)-------------------------------------------非递归b0::对于所有(a::元组)。[]>>=ab0[]=暂停(())-------------------------------------------非递归b81::针对所有(a::*)。[Dup a]>>=[Dup a]b81【t0】=第t0个案例,共个案例重复->b84[t0]_->b0[]-------------------------------------------非递归k54::对于所有(a::*)。{}[重复a]->>[重复a]k54{}t0=b81[t0]-------------------------------------------非递归s2::对于所有(a::*)。[重复a]->>[重复a]第2页<-k54{}-------------------------------------------非递归交换::对于所有(a::*)。重复->重复互换<-函数(s2)-------------------------------------------非递归入口点swap8::重复(Bit 8)->重复(Bit8)拭子8<-回报互换-------------------------------------------非递归入口点swap7::重复(Bit 7)->重复(Bit7)拭子7<-回报互换-------------------------------------------入口点:d1 swap8 swap7$

这里需要注意的一个细节是函数值喜欢互换在构造函数的使用中被包装起来功能,它是作为(内置)数据类型定义的结果引入的数据d->r=函数([d]->>[r])。您可能还注意到块中的case构造b81号包括默认分支(引入使用下划线而不是构造函数名称),即使杜普它所匹配的类型只有一个构造函数。我们可以通过包括c(c)pass(“构造函数函数重写”)作为-第页设置:

$milc-ilib-m演示/ex.lc-pco数据重复(a::*)=重复-------------------------------------------非递归入口点d1::重复(位3)第1天<-Dup(B001、B110)-------------------------------------------非递归b80::用于所有(a::*)。[重复a]>>=[重复a]b80【t0】=t1<-重复0 t0t2<-重复1 t0重复(t2,t1)-------------------------------------------非递归k54::对于所有(a::*)。{}[重复a]->>[重复a]k54{}t0=b80[t0]-------------------------------------------非递归交换::对于所有(a::*)。[Dup a]->>互换<-k54{}-------------------------------------------非递归入口点swap8::[重复(Bit 8)]->>[重复(Bit 8)]拭子8<-回报互换-------------------------------------------非递归入口点swap7::[重复(Bit 7)]->>[重复(Bit 7)]拭子7<-回报互换-------------------------------------------入口点:d1 swap8 swap7$

转换后,所有对LC级函数的引用类型构造器->已被MIL功能的使用所取代键入箭头->>。一般来说,如果源程序包含非递归数据类型的定义数据T a=MkT T,然后这个c(c)pass将消除所有时间类型(和所有用途百万吨构造函数),将其替换为相应的的实例t吨.

下一步,我们可以消除多态性和参数化通过运行specializer从MIL程序中获取数据类型,表示为凭通行证:(我们在此使用第二个优化器运行,只是为了清理结果代码,但这不是技术上的必修的。或者,我们可以实现与此处使用显示-多氯联苯,它只使用一个优化器过程。)

$milc-ilib-m演示/例如lc-pcoso数据Dup0=Dup0(第7位)(第7位元)数据Dup1=Dup1(第8位)(第8位元)数据Dup2=重复2(第3位)(第3位元)-------------------------------------------非递归b80::[Dup0]>>=[Dup0]b80【t0】=t1<-Dup0 0 t0t2<-Dup0 1 t0Dup0(t2,t1)-------------------------------------------非递归k54::{}[Dup0]->[Dup0]k54{}t0=b80[t0]-------------------------------------------非递归交换::[Dup0]->[Dup0]互换<-k54{}-------------------------------------------非递归入口点swap7::[Dup0]->[Dup0]拭子7<-回报互换-------------------------------------------非递归b801::[重复1]>>=[重复1]b801【t0】=t1<-重复1 0 t0t2<-重复1 1 t0Dup1(t2,t1)-------------------------------------------非递归k541::{}[Dup1]->[Dup1]k541{}t0=b801[t0]-------------------------------------------非递归s1::[重复1]->>[重复1]第1页<-k541{}-------------------------------------------非递归入口点交换8::[Dup1]->[Dup1]拭子8<-返回s1-------------------------------------------非递归入口点d1::Dup2第1天<-Dup2(B001、B110)-------------------------------------------入口点:swap7 swap8 d1$

现在生成的程序更长,因为的两个不同副本互换函数,每个函数都在不同版本的杜普类型。然而,按照预期程序不再包含任何多态类型的定义。

为了生成这个程序的工作代码,我们需要为以下类型提供表示形式第7位第8位那个出现在这个节目中。在mil-tool中,这两种类型都是实际表示为类型的值单词,仅治疗在每种情况下,降低7或8位为有效。这个第页字符可用于指定“表示转换”通过重写输入程序以显示这些低级别细节:

$milc-ilib-m演示/ex.lc-pcosoro数据Dup0=Dup0单词-------------------------------------------非递归入口点交换7::[Dup0]>>=[Dup0]交换7[t0]=t1<-Dup0 0 t0t2<-Dup0 1 t0Dup0(t2,t1)-------------------------------------------非递归入口点swap8::[Dup0]>>=[Dup0]拭子8[t0]=t1<-重复0 t0t2<-Dup0 1 t0Dup0(t2,t1)-------------------------------------------非递归入口点d1::Dup0第1天<-Dup0(1,6)-------------------------------------------入口点:swap7 swap8 d1$

对于以下类型Dup0型但是,可以通过替换每个与相应位数据关联的数据类型定义定义。这可以通过使用字母来实现b条指定位数据重写传递。请注意b条可以仅在之后立即使用因为它依赖于专业化过程中生成的信息:

$milc-ilib-m演示/ex.lc-pcosbo位数据Dup0/14=Dup0[Dup00::位7 | Dup01::位7]--predDup0(x::位14)=真--位模式:--  ______________位数据重复1/16=Dup1[Dup10::位8 | Dup11::位8]--predDup1(x::位16)=真--位模式:--  ________________位数据Dup2/6=Dup2[Dup20::位3 | Dup21::位3]--predDup2(x::Bit 6)=真--位模式:--  ______-------------------------------------------非递归b80::[Dup0]>>=[Dup0]b80【t0】=t1<-Dup0 0 t0t2<-重复0.重复0 t1t3<-Dup0.Dup0 1 t1t4<-Dup0.Dup0(t3,t2)Dup0(t4)-------------------------------------------非递归k54::{}[Dup0]->[Dup0]k54{}t0=b80[t0]-------------------------------------------非递归交换::[Dup0]->[Dup0]互换<-k54{}-------------------------------------------非递归入口点swap7::[Dup0]->[Dup0]拭子7<-回报互换-------------------------------------------非递归b801::[重复1]>>=[重复1]b801【t0】=t1<-重复1 0 t0t2<-Dup1.Dup1 0 t1t3<-重复1。重复1 1 t1t4<-重复1。重复1(t3,t2)Dup1(t4)-------------------------------------------非递归k541::{}[Dup1]->[Dup1]k541{}t0=b801[t0]-------------------------------------------非递归s1::[重复1]->>[重复1]第1页<-k541{}-------------------------------------------非递归入口点交换8::[Dup1]->[Dup1]拭子8<-返回s1-------------------------------------------非递归s2::Dup2.Dup2s2秒<-Dup2、Dup2(B001、B110)-------------------------------------------非递归入口点d1::Dup2第1天<-Dup2(s2)-------------------------------------------入口点:swap7 swap8 d1$

如果你想知道为什么这个版本的程序看起来稍微长一点,因为位数据类型使用两种构造函数功能的级别:针对每个构造函数功能C类位数据类型中T型,还有一个关联的已调用布局类型T.C公司,每个都有一个构造函数具有相同名称的函数。

此时,我们可以添加第页回到我们的传球名单运行表示转换。在这一点上,军事行动决定了这一点Dup0型重复1可以用一个单词表示(只有16位和14位,在每种情况下都需要0)并替换代数数据类型选择器和构造函数适当的比特旋转逻辑,如最终输出如下所示:

$milc-ilib-m演示/ex.lc-pcosboro-------------------------------------------非递归入口点swap7::[Word]>>=[Word]拭子7[t0]=t1<-lshr((t0,7))t2<-shl((t0,7))t3<-和(t216256)或((t1,t3))-------------------------------------------非递归入口点swap8::[Word]>=[Word]拭子8[t0]=t1<-lshr((t0,8))t2<-shl((t0,8))t3<-和(t265280)或((t1,t3))-------------------------------------------非递归入口点d1::Word第1天<-返回14-------------------------------------------入口点:swap7 swap8 d1$

还要注意,作为第页表示变换,的定义拭子8拭子7已从更改函数闭包的定义(使用->>箭头)至简单块定义,作为标准更容易访问来自其他LLVM语言的函数,如我们切换时所示在前一示例中,从MIL到LLVM输出:(可能用一次mil-tools调用来生成这两者,但我们只在这里一次生成一个,这样输出就容易一些

$milc-ilib-l演示/ex.lc-pcosboro@d1=全局i32 14定义i32@swap7(i32%r0){条目:br标签%swap7拭子7:%r2=lshr i32%r0,7%r4=shl i32%r0,7%r3=和i32%r416256%r1=或i32%r2,%r3第32列第1列}定义i32@swap8(i32%r0){条目:br标签%swap8拭子8:%r2=lshr i32%r0,8%r4=shl i32%r0,8%r3=和i32%r4,65280%r1=或i32%r2,%r3第32列第1列}$

函数库、独立程序和变体

这里描述的工具可以用多种方式支持开发软件库、独立程序或两者之间的变化。以下示例说明了一些以及LC/MIL功能的相应使用和milc命令行选项。

函数库

我们的第一个示例是一个小型函数库完整的程序,但可能链接作为各种不同应用程序的有用组件。这个特定的库,其源代码位于演示/funlib.lc提供了Fibonnaci函数的两个实现,以及两个阶乘函数的实现,因此它可能在许多现实环境中没有用处,但应该提供一些熟悉的例子,也应该足以证明主要思想:

$cat演示/funlib.lc要求“序言.lc”--Fibonnaci函数的标准递归版本:入口点fib::Word->Wordfib n=如果方程n为0,则为0否则,如果等式n为1,则为1else相加(fib(子n 1))(fib(子n 2))--Fibonnaci函数的迭代版本:入口点itfib::Word->Worditfib=让循环a b n=如果方程n为0,则另一个循环b(添加a b)(子n 1)循环0 1中--阶乘函数的传统递归实现:入口点recfac::Word->Wordrecfac n=如果eq n为0,则为1,否则为mul n(recfac(sub n 1))--阶乘函数的迭代版本:入口点itfac::Word->Worditfac=让循环a n=如果方程n为0,则为else循环(mula n)(子n 1)回路1中$

也许这里最重要的细节是四个函数被声明为入口点.(类型签名这里提供的每个函数都可以用作文档,但它们也可以自动推断,因此实际上并非如此必需。)因此,当使用按照以下命令,它将生成LLVM输出(在文件中tmp/funlib.ll)包含外部可见函数的四个LC函数中每一个的定义。

$milc-ilib演示/funlib.lc-ltmp/funlib.ll$clang-c-o tmp/funlib.o tmp/funnib.ll警告:使用…覆盖模块目标三元组。。。生成1个警告。$

[如前所述,假设您有一个传统的LLVM安装,您应该可以忽略此处显示的警告消息。]

上面显示的命令序列遵循密尔克用一个叮当作响生成对象文件的命令tmp/funlib。o(o)那可以与其他程序链接。或者,我们可以写一个C使用中函数的程序funlib.lc然后使用单一的叮当作响命令编译并将其链接到tmp/funlib.ll源文件:

$cat演示/funlibtest.c#包括<stdio.h>外部int fib(int);外部int itfib(int);外部内部recfac(int);外部内部itfac(int);int main(int argc,char**argv){对于(int i=0;i<10;i++){printf(“%d\t%d\t%t\t%d\t%d\t%d”,i、 fib(i)、itfib(i)、recfac(i)和itfac(i));}}$clang-o tmp/funlibtest演示/funlibtest.c tmp/funnib.ll$

[注:在macOS上,您可以(或需要)替换海湾合作委员会对于叮当作响在此处显示的命令行中,具体取决于LLVM安装。]

注意,C代码引用了我们已经看到的函数定义于funlib.lc作为常规C函数功能原型。这是可能的,因为如果入口点在LC代码中是一个curried函数,然后将其导出将生成的LLVM代码作为完全未绑定函数(即。,作为一个同时接受所有参数的函数是C语言中不直接支持的规范高阶函数)。结果是一个混合的可执行文件将两个不同源代码组件中的代码转换为单个程序:

$tmp/funlibtest0       0       0       1       11       1       1       1       12       1       1       2       23       2       2       6       64       3       3       24      245       5       5       120     1206       8       8       720     7207       13      13      5040    50408       21      21      40320   403209       34      34      362880  362880$

初始化功能

虽然在我们的funlib语言例子,有时需要执行某种初始化库中某些(或所有)入口点之前的步骤是第一次使用。以下显示了一个人为的包含名为图12图15应该包含12号和15号斐波那契数:

$cat演示/needinit.lc要求“prelude.lc”入口点fib::Word->Wordfib n=如果方程n为0,则为0否则,如果等式n为1,则为1else相加(fib(子n 1))(fib(子n 2))入口点fib12,fib15fib12=fib 12fib15=fib 15$

但现在假设我们将其与一个C程序链接,该程序读取的值图12图15并在屏幕上显示。计算这些值的点是什么?如果我们编译这个程序使用类似密尔克上一个命令行例如,我们得到一个错误,通知我们生成的代码需要初始化函数:

$milc-ilib演示/needinit.lc-ltmp/neediti.ll错误:LLVM程序需要初始化函数(使用--LLVM-main=NAME设置)$

在这个特定的示例中,需要一个初始化函数计算的值图12图15,为了挽救这些相应变量中的值。一般来说需要初始化函数的任何程序都需要变量或内存区域的一次性初始化使用了程序的部分内容。

错误消息还建议我们可以通过以下方式解决此问题使用--llvm-main公司命令行选项,即我们在下面所做的,选择使用名称初始化对于此函数:

$milc-ilib demo/needinit.lc-ltmp/needinit.ll--llvm-main=初始化$

现在我们可以编写使用需要初始化库。而且,只要我们确保初始化()函数被调用在的值之前图12图15被访问,然后变量将被正确初始化,一切正常如预期:

$cat演示/printfibs.c#包括<stdio.h>外部void initialize();外部int fib12,fib15;int main(int argc,char**argv){initialize();printf(“fib(12)=%d,fib(15)=%d\n”,fib12,fib15);}$clang-o tmp/printfibs演示/printfibs.c tmp/needinit.ll$tmp/printfibsfib(12)=144,fib(15)=610$

实际上,可能很难确定实际上不需要初始化函数,缺少运行密尔克类似于上面的命令行,以查看报告了错误。例如,如果我们替换小谎功能在里面需要init.lc效率更高itfib公司函数,然后mil-tools优化器实际上能够计算值属于纤维12纤维15在编译时,不会有任何需要初始化函数。因此,通常使用指定初始化函数名的良好实践这个--llvm-main公司选项并鼓励库用户在尝试访问其任何其他函数之前调用该函数特征。如果图书馆实际上不需要特殊处理,然后密尔克将生成一个初始化函数空的身体。但是如果程序随后发生了变化这需要正确的初始化,然后库的用户,至少如果他们听从了你的建议,就会已经在代码中包含适当的函数调用。

编写独立程序

在前面的示例中,我们用访问的LC编写了代码并从主要的函数用C编写。但如果我们想写我们的主要的直接在LC中编程,如下面是显示值的简单示例图12:

$cat演示/程序.lc要求“序言.lc”需要“io.mil”itfib::单词->单词itfib=让循环a b n=如果方程n为0,则另一个循环b(添加a b)(子n 1)循环0 1中--打印第12个Fibonnaci数字的程序:出口总管main=打印Word(itfib 12)$

此程序没有指定任何显式入口点,但它包含的定义主要的标记为的例程一个出口。这使我们可以使用--独立的标志密尔克:

$milc-ilib--独立演示/program.lc-ltmp/program.ll$clang-o tmp/program tmp/progrem.ll演示/运行时.c警告:使用…覆盖模块目标三元组。。。生成1个警告。$tmp/程序144$

请注意,尽管名称是什么--独立的可能会建议,这个叮当作响这里显示的命令行实际上提到了C源文件演示/运行时。c(c),它提供了的实现打印Word原始函数LC代码。所以,事实上,我们仍然在混合LC和C代码,但这次我们从LC代码调用C代码,这与我们在前面的例子中看到的相反。

这个--独立的flag实际上只是以下两个命令行选项:

--llvm-main=main--mil-main=main

正如我们已经看到的,其中第一个指定生成的LLVM代码应包含初始化函数打电话主要的第二个定义确定了一个特定的定义名字是主要的,但这次在输入程序,即将在初始化函数结束时执行。最多的一个主要的可以用这种方式指定定义,但它是可以使用具有不同名称的值,只要它是标记为出口在源程序中,并使用标识明确的--mil main=名称在命令行上设置。)While期间--独立的为以下两项提供合理的默认值这些命令行选项,单独的--米尔曼--llvm-main公司选项提供有用的附加控制在一些更高级的设置中。

关于

MIL工具,一种Monadic中间语言

资源

许可证

星星

观察者

叉子

发布

未发布版本

包装

未发布包

贡献者4

  •  
  •  
  •  
  •  

语言文字