编译器

c++中extern "c"的使用

别等时光非礼了梦想. 提交于 2020-03-16 00:02:50
比如说你用C 开发了一个DLL 库,为了能够让C ++语言也能够调用你的DLL 输出(Export) 的函数,你需要用extern "C" 来强制编译器不要修改你的函数名。 通常,在C 语言的头文件中经常可以看到类似下面这种形式的代码: C代码 #ifdef __cplusplus extern "C" { #endif /**** some declaration or so *****/ #ifdef __cplusplus } #endif 那么,这种写法什么用呢?实际上,这是为了让CPP 能够与C 接口而采用的一种语法形式。之所以采用这种方式,是因为两种语言之间的一些差异所导致的。由于CPP 支持多态性,也就是具有相同函数名的函数可以完成不同的功能,CPP 通常是通过参数区分具体调用的是哪一个函数。在编译的时候,CPP 编译器会将参数类型和函数名连接在一起,于是在程序编译成为目标文件以后,CPP 编译器可以直接根据目标文件中的符号名将多个目标文件连接成一个目标文件或者可执行文件。但是在C 语言中,由于完全没有多态性的概念,C 编译器在编译时除了会在函数名前面添加一个下划线之外,什么也不会做(至少很多编译器都是这样干的)。由于这种的原因,当采用CPP 与C 混合编程的时候,就可能会出问题。假设在某一个头文件中定义了这样一个函数: int foo(int a, int b);

从零开始开发JVM语言(二)词法分析

若如初见. 提交于 2020-02-29 10:28:29
目录戳 这里 词法分析的工作是,将输入的字符串转化为结构清晰的 Token 通常来说,这个 Token 需要包含两样东西,词 和 类型 ##词 什么是词呢?例如,输入串如下: val num = 3 * 7 从直觉上(语法高亮也帮助了我们)可以看出,它由如下几部分组成 val num = 3 * 7 我们不会把 val 拆成 v al 或者其他什么形式,因为它是一个“词” “词”表示用于解析的最小单元。词的规定很宽泛,像emoji语言,它的一个词很可能就是一个emoji图像(虽然我没研究过不过大概如此吧。。)而对于主流的编程语言,词通常为一串字母,数字,某些特殊符号(运算符) 注:如下方式的原理和自动机一致,但是性能没有自动机高。好处在于手写实现几乎不可能出错。 在 Latte 中,词有如下规定 Scanner.java#L95 如下的符号 // SPLIT ".", ":", "::", "=", "+=", "-=", "*=", "/=", "%=", "<<", ">>", ">>>", "&", "^", "|", "~", "^^", "!", "&&", "||", "!=", "==", "!==", "===", "<", ">", "<=", ">=", "+", "-", "*", "/", "%", "++", "--", "@", "=:=", "!:="

llvm每日谈之二 LLVM IR

北城以北 提交于 2020-02-29 07:47:18
作者: snsn1984 在介绍LLVM IR之前,我们需要先了解下LLVM的结构。传统的静态编译器分为三个阶段:前端、优化和后端。 LLVM的三阶段设计是这样的: 这样做的优点是如果需要支持一种新的编程语言,那么我们只需要实现一种新的前端。如果我们需要支持一种新的硬件设备,那我们只需要实现一个新的后端。而优化阶段因为是针对了统一的LLVM IR,所以它是一个通用的阶段,不论是支持新的编程语言,还是支持新的硬件设备,这里都不需要对优化阶段做修改。所以从这里可以看出LLVM IR的作用。 LLVM IR主要有三种格式:一种是在内存中的编译中间语言;一种是硬盘上存储的二进制中间语言(以.bc结尾),最后一种是可读的中间格式(以.ll结尾)。这三种中间格式是完全相等的。 LLVM IR是LLVM优化和进行代码生成的关键。根据可读的IR,我们可以知道再最终生成目标代码之前,我们已经生成了什么样的代码。而且根据IR,我们可以选择使用不同的后端而生成不同的可执行代码。同时,因为使用了统一的IR,所以我们可以重用LLVM的优化功能,即使我们使用的是自己设计的编程语言。 如果想直观的看下llvm的IR到底是什么样的,可以先写一个helloworld的程序,文件名字叫做hello.c。根据下列文档的步骤配置llvm: http://clang.llvm.org/get_started.html

实现一个简单的编译器

浪子不回头ぞ 提交于 2019-12-20 00:54:37
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 简单的说 编译器 就是语言翻译器,它一般将高级语言翻译成更低级的语言,如 GCC 可将 C/C++ 语言翻译成可执行机器语言,Java 编译器可以将 Java 源代码翻译成 Java 虚拟机可以执行的字节码。 编译器如此神奇,那么它到底是如何工作的呢?本文将简单介绍编译器的原理,并实现一个简单的编译器,使它能编译我们自定义语法格式的源代码。(文中使用的源码都已上传至 GitHub 以方便查看)。 自定义语法 为了简洁易懂,我们的编译器将只支持以下简单功能: 数据类型只支持整型,这样不需要数据类型符; 支持 加(+) , 减(-) , 乘(*) , 除(/) 运算 支持函数调用 支持 extern (为了调用 printf 打印计算结果) 以下是我们要支持的源码实例 demo.xy : extern printi(val) sum(a, b) { return a + b } mult(a, b) { return a * b } printi(mult(4, 5) - sum(4, 5)) 编译原理简介 一般编译器有以下工作步骤: 词法分析(Lexical analysis): 此阶段的任务是从左到右一个字符一个字符地读入源程序,对构成源程序的字符流进行扫描然后根据构词规则识别 单词(Token)

有写编译器的冲动?进来看看!(转)

本秂侑毒 提交于 2019-12-10 15:49:34
http://blog.csdn.net/lm2302293/article/details/6798765 工作如果是和编译器相关的或者编译器爱好者们,谁没有点冲动想自己写个编译器出来。我也做了一些调研,分享如下: How to write your own compiler 介绍如何使用Java语言完成一个面向LLVM后端的编译器。 以mjava作为目标语言,mjava是Java语言的一个子集。 包括词法分析,语法分析,错误控制,符号表管理,类型检查等部分。 Hey Kids, Let’s Write a Compiler Today! 采用一种逐步增加功能的方式构造编译器。作者的文章写得深入浅出(我只看了abstract和introduction部分)。 Let’s Build a Compiler, by Jack Crenshaw 作者从1988-1995年用了 7年的时间 完成了这份介绍。没有使用Flex和yacc这些东西,纯手工制作。使用Pascal语言写出的编译器。是一位学物理的博士,很是钦佩! MIT OCW 6.035 Computer Language Engineering MIT 关于计算机工程的开放课程,使用Java语言创建一个完整的Decaf语言编译器。我也曾看过一点,但这门课的实验要求有MIT的环境,还有一些库什么的。外面的人拿不到,所以没办法

llvm每日谈之三 如何创建一个LLVM工程

[亡魂溺海] 提交于 2019-12-10 08:15:24
作者: snsn1984 阅读了文档《Creating an LLVM Project》(地址:http://llvm.org/docs/Projects.html)之后,自己照着做了一遍,记录一下自己的过程。 实际做的时候跟文档上还是有不同的。 1.首先我系统上的llvm3.1是之前已经下好,并且make过的。我打开llvm-3.1/projects目录,看到下面有一个我之前放的compiler-rt目录和另外一个本来这里就有的sample。把sample这个文件夹copy到llvm3.1的同级目录。修改文件夹名字为MyFirstLLVM。 2. 打开MyFirstLLVM/autoconf目录,打开configure.ac. 3. AC_INIT后面的括号里面有三个中括号,第一个中括号要填的是这个项目的名字,第二个是这个项目的版本号,第三个是作者的联系邮箱,可改可不改。 4. 因为现在MyFirstLLVM已经和llvm-3.1在同级目录了,所以修改接下来的LLVM_SRC_ROOT="../../llvm-3.1" LLVM_OBJ_ROOT="../../llvm-3.1/build"。llvm-3.1/build目录是我编译llvm-3.1的目录。 5. 修改AC_CONFIG_AUX_DIR后面的内容为:(["../../llvm-3.1/autoconf"])。 6.

llvm每日谈之一 llvm是什么

徘徊边缘 提交于 2019-12-10 08:03:34
作者: snsn1984 写在前面的话: 最近接触llvm比较多,在这个上面花了不少的时间。感 觉llvm要完全理解透是个很不容易的事情,需要在学习过程中好好的整理下自己的思路。刚好又阅读了开源项目Storm的作者Nathan Marz的博客《You should blog even if you have no readers》,就打开自己的blog,开始了这个llvm每日谈的系列。希望自己能坚持的久一点,多写写llvm的每个方面,多写写自己的理解。 欢迎感兴趣的人一起探讨研究。 llvm是什么? llvm是low level virtual machine的简称,其实是一个编译器框架。llvm随着这个项目的不断的发展,已经无法完全的代表这个项目了,只是这种叫法一直延续下来。 llvm是一个开源的项目。它最早的时候是Illinois的一个研究项目,主要负责人是Chris Lattner,他现在就职于Apple. Apple 目前也是llvm项目的主要赞助者之一。 llvm的主要作用是它可以作为多种语言的后端,它可以提供可编程语言无关的优化和针对很多种CPU的代码生成功能。此外llvm目前已经不仅仅是个编程框架,它目前还包含了很多的子项目,比如最具盛名的clang. llvm的优点是开源,有一个表达形式很好的IR语言,模块化作的特别好。

LLVM每日谈之七 Clang

血红的双手。 提交于 2019-12-10 06:36:58
作者: snsn1984 官方介绍Clang是LLVM native的一个面向C/C++/Objective-C的编译器,目标是要提供一个编译非常快的编译器。他们宣称在Debug模式下编译Objective-C比GCC快3倍。至于是否能比GCC快这么多,总有人去做对比,大家可以搜索下,好像确实快了些。 Clang一般被说是LLVM的一个前端。关于前端的定义,大家可以从LLVM每日谈之二里面看到前端在整个LLVM体系中的位置。Clang当初的定位就是要做下一个十年中一个伟大的前端,这也是苹果公司需要的。谈到苹果,现在也是LLVM最大的赞助商。苹果公司认为GCC的前端越来越不好用,并且不能给苹果的IDE提供很好的服务,所以他们转向了LLVM,Clang的定位就是替代GCC的前端。 Clang需要单独下载源码,放到LLVM Source/tools下面,然后整个编译LLVM才行。一般大家按照官方文档编译,都是已经放了Clang了。开始学习Clang文档的地址: http://clang.llvm.org/get_started.html 。这里下载源码的话使用svn下载的是最新的主干版本,大家可以从首页找到最后的发布版本的下载, 地址在: http://llvm.org/releases/ 。这里可以看到发布的各个版本,目前最新的是3.1, 马上3.2就要出来了

LLVM每日谈之六 LLVM的源码结构

a 夏天 提交于 2019-12-09 21:09:50
作者: snsn1984 这里简单介绍下LLVM的源码结构,让大家知道LLVM的每个文件夹都放的是什么内容。 参考文档: http://llvm.org/docs/GettingStarted.html#getting-started llvm/examples 这个目录主要是一些简单例子,演示如何使用LLVM IR 和 JIT。还有建立一个简单的编译器的例子的代码。 建立简单编译器的文档地址:http://llvm.org/docs/tutorial/ llvm/include 这个目录主要包含LLVM library的公共头文件。 llvm/lib 这个目录包含了大部分的LLVM的源码。在LLVM中大部分的源码都是以库的形式存在的,这样不同的工具之前就很容易共用代码。 llvm/projects 这个目录包含着一些依赖LLVM的工程,这些工程严格来说又不算LLVM一部分。 llvm/runtimes 这个目录包含了一些库,这些库会编译成LLVM的bitcode,然后当clang linking 程序的时候使用。 llvm/test 这个目录是LLVM的测试套件,包含了很多测试用例,这些测试用例是测试LLVM的所有基本功能的。 llvm/tools 这个目录理是各个工具的源码,这些工具都是建立在刚才上面的那些库的基础之上的。也是主要的用户接口。 llvm/utils

llvm每日谈之四 Pass初探

╄→гoц情女王★ 提交于 2019-12-09 21:00:21
作者: snsn1984 LLVM 的Pass框架是LLVM系统的一个很重要的部分。每个Pass都是做优化或者转变的工作,LLVM的优化和转换工作就是由很多个Pass来一起完成的。 所 以按照我的理解,Pass就是LLVM系统转化和优化的工作的一个节点,每个节点做一些工作,这些工作加起来就构成了LLVM整个系统的优化和转化。 Pass架构这么做的话,可重用性非常好,你可以选择已有的一些Pass,自己去构建出自己想要的优化和转化效果。并且自己也可以重新写Pass去做自己 想要的优化和转变,因为每个Pass都可以独立存在,所以新建Pass并不用考虑LLVM之前的优化和转化是怎么做的,自己可以只运行自己新建的 Pass,这样可以方便的实现自己想要的效果。 Pass最初的例子就在:llvm源码/lib/Transform/Hello/Hello.cpp。 可以采用命令 $ opt -load ../../../Debug+Asserts/lib/Hello.so -hello < hello.bc > /dev/null 去运行这个Pass,并且查看效果。 ../../../Debug+Asserts/lib/Hello.so 是so的目录,在llvm3.1中,这个例子的名称已经变成了LLVMHello.so. 存放在build目录/Release+Asserts/lib目录之下