ubuntu 22.04 LTS 在 llvm release/17.x 分支上编译 cookbook llvm example Chapter 02

news2024/11/24 11:56:50

下载 llvm-cookbook example:

$ git clone https://github.com/elongbug/llvm-cookbook.git

开发环境:

 从apt source 安装llvm、clang和lldb:

$ apt install llvm
$ apt install llvm-dev
$ apt install clang
$ apt install lldb
$ cd llvm-cookbook/Chapter_2
$ make
$ ./toy example1

 运行效果:

 

 ————————————————————————————————————————

一,从源码编译 llvm

下载源码:

$ git clone https://github.com/llvm/llvm-project.git

创建 对应 commit id分支:

$ cd llvm-project
$ git checkout  5b78868661f42a70fa30  -b  17.x.greater

源码成功编译 llvm-project commit id:

    ~/ex/llvm-project$ git log -1
    commit 5b78868661f42a70fa3006b1db41f78a6178d596 (HEAD -> main)

 生成构建:

cmake -G "Unix Makefiles" ../llvm    \
-DLLVM_ENABLE_PROJECTS=all           \
-DLLVM_BUILD_EXAMPLES=ON             \
-DLLVM_TARGETS_TO_BUILD="host"       \
-DCMAKE_BUILD_TYPE=Release           \
-DLLVM_ENABLE_ASSERTIONS=ON          \
-DLLVM_ENABLE_RUNTIMES=all           \
-DLLVM_BUILD_LLVM_DYLIB=ON           \  
-DCMAKE_INSTALL_PREFIX=../inst_clanglld_rtall_5b78868661

make -j8

(i9 9900k 8物理core 16logic core, 64GB mem, 64GB swap)

make install

二,编译Chapter2 example

可行的 Makefile:

CC = /home/kleenelan/ex/cookbook_llvm/inst_clanglld_rtall_5b78868661/bin/clang++
SOURCE = ch2_toy.cpp
TARGET = toy

$(TARGET) : $(SOURCE)
        $(CC) $(SOURCE) -o  $(TARGET) -g  `/home/kleenelan/ex/cookbook_llvm/inst_clanglld_rtall_5b78868661/bin/llvm-config --cxxflags --ldflags --system-libs --libs core mcjit native` -I/home/kleenelan/ex/cookbook_llvm/inst_clanglld_rtall_5b78868661/include/c++/v1   -I/home/kleenelan/ex/cookbook_llvm/inst_clanglld_rtall_5b78868661/include/x86_64-unknown-linux-gnu/c++/v1  -L/usr/lib/gcc/x86_64-linux-gnu/11/  -L/home/kleenelan/ex/cookbook_llvm/inst_clanglld_rtall_5b78868661/lib/x86_64-unknown-linux-gnu -lc++

clean :
        rm $(TARGET)

ch2_toy.cpp

#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include <cctype>
#include <cstdio>
#include <map>
#include <string>
#include <vector>
using namespace llvm;

enum Token_Type { EOF_TOKEN = 0, DEF_TOKEN, IDENTIFIER_TOKEN, NUMERIC_TOKEN };

FILE *file;
static std::string Identifier_string;
static int Numeric_Val;

static int get_token() {
  static int LastChar = ' ';

  while (isspace(LastChar))
    LastChar = fgetc(file);

  if (isalpha(LastChar)) {
    Identifier_string = LastChar;
    while (isalnum((LastChar = fgetc(file))))
      Identifier_string += LastChar;

    if (Identifier_string == "def")
      return DEF_TOKEN;

    return IDENTIFIER_TOKEN;
  }

  if (isdigit(LastChar)) {
    std::string NumStr;
    do {
      NumStr += LastChar;
      LastChar = fgetc(file);
    } while (isdigit(LastChar));

    Numeric_Val = strtod(NumStr.c_str(), 0);
    return NUMERIC_TOKEN;
  }

  if (LastChar == '#') {
    do
      LastChar = fgetc(file);
    while (LastChar != EOF && LastChar != '\n' && LastChar != '\r');

    if (LastChar != EOF)
      return get_token();
  }

  if (LastChar == EOF)
    return EOF_TOKEN;

  int ThisChar = LastChar;
  LastChar = fgetc(file);
  return ThisChar;
}

namespace {

class BaseAST {
public:
  virtual ~BaseAST() {}
  virtual Value *Codegen() = 0;
};

class NumericAST : public BaseAST {
  int numeric_val;

public:
  NumericAST(int val) : numeric_val(val) {}
  virtual Value *Codegen();
};

class VariableAST : public BaseAST {
  std::string Var_Name;

public:
  VariableAST(const std::string &name) : Var_Name(name) {}
  virtual Value *Codegen();
};

class BinaryAST : public BaseAST {
  std::string Bin_Operator;
  BaseAST *LHS, *RHS;

public:
  BinaryAST(std::string op, BaseAST *lhs, BaseAST *rhs)
      : Bin_Operator(op), LHS(lhs), RHS(rhs) {}
  virtual Value *Codegen();
};

class FunctionCallAST : public BaseAST {
  std::string Function_Callee;
  std::vector<BaseAST *> Function_Arguments;

public:
  FunctionCallAST(const std::string &callee, std::vector<BaseAST *> &args)
      : Function_Callee(callee), Function_Arguments(args) {}
  virtual Value *Codegen();
};

class FunctionDeclAST {
  std::string Func_Name;
  std::vector<std::string> Arguments;

public:
  FunctionDeclAST(const std::string &name, const std::vector<std::string> &args)
      : Func_Name(name), Arguments(args){};
  Function *Codegen();
};

class FunctionDefnAST {
  FunctionDeclAST *Func_Decl;
  BaseAST *Body;

public:
  FunctionDefnAST(FunctionDeclAST *proto, BaseAST *body)
      : Func_Decl(proto), Body(body) {}
  Function *Codegen();
};
} // namespace

static int Current_token;
static int next_token() { return Current_token = get_token(); }

static std::map<char, int> Operator_Precedence;

static int getBinOpPrecedence() {
  if (!isascii(Current_token))
    return -1;

  int TokPrec = Operator_Precedence[Current_token];
  if (TokPrec <= 0)
    return -1;
  return TokPrec;
}

static BaseAST *expression_parser();

static BaseAST *identifier_parser() {
  std::string IdName = Identifier_string;

  next_token();

  if (Current_token != '(')
    return new VariableAST(IdName);

  next_token();

  std::vector<BaseAST *> Args;
  if (Current_token != ')') {
    while (1) {
      BaseAST *Arg = expression_parser();
      if (!Arg)
        return 0;
      Args.push_back(Arg);

      if (Current_token == ')')
        break;

      if (Current_token != ',')
        return 0;
      next_token();
    }
  }
  next_token();

  return new FunctionCallAST(IdName, Args);
}

static BaseAST *numeric_parser() {
  BaseAST *Result = new NumericAST(Numeric_Val);
  next_token();
  return Result;
}

static BaseAST *paran_parser() {
  next_token();
  BaseAST *V = expression_parser();
  if (!V)
    return 0;

  if (Current_token != ')')
    return 0;
  return V;
}

static BaseAST *Base_Parser() {
  switch (Current_token) {
  default:
    return 0;
  case IDENTIFIER_TOKEN:
    return identifier_parser();
  case NUMERIC_TOKEN:
    return numeric_parser();
  case '(':
    return paran_parser();
  }
}

static BaseAST *binary_op_parser(int Old_Prec, BaseAST *LHS) {
  while (1) {
    int Operator_Prec = getBinOpPrecedence();

    if (Operator_Prec < Old_Prec)
      return LHS;

    int BinOp = Current_token;
    next_token();

    BaseAST *RHS = Base_Parser();
    if (!RHS)
      return 0;

    int Next_Prec = getBinOpPrecedence();
    if (Operator_Prec < Next_Prec) {
      RHS = binary_op_parser(Operator_Prec + 1, RHS);
      if (RHS == 0)
        return 0;
    }

    LHS = new BinaryAST(std::to_string(BinOp), LHS, RHS);
  }
}

static BaseAST *expression_parser() {
  BaseAST *LHS = Base_Parser();
  if (!LHS)
    return 0;
  return binary_op_parser(0, LHS);
}

static FunctionDeclAST *func_decl_parser() {
  if (Current_token != IDENTIFIER_TOKEN)
    return 0;

  std::string FnName = Identifier_string;
  next_token();

  if (Current_token != '(')
    return 0;

  std::vector<std::string> Function_Argument_Names;
  while (next_token() == IDENTIFIER_TOKEN)
    Function_Argument_Names.push_back(Identifier_string);
  if (Current_token != ')')
    return 0;

  next_token();

  return new FunctionDeclAST(FnName, Function_Argument_Names);
}

static FunctionDefnAST *func_defn_parser() {
  next_token();
  FunctionDeclAST *Decl = func_decl_parser();
  if (Decl == 0)
    return 0;

  if (BaseAST *Body = expression_parser())
    return new FunctionDefnAST(Decl, Body);
  return 0;
}

static FunctionDefnAST *top_level_parser() {
  if (BaseAST *E = expression_parser()) {
    FunctionDeclAST *Func_Decl =
        new FunctionDeclAST("", std::vector<std::string>());
    return new FunctionDefnAST(Func_Decl, E);
  }
  return 0;
}

static void init_precedence() {
  Operator_Precedence['-'] = 1;
  Operator_Precedence['+'] = 2;
  Operator_Precedence['/'] = 3;
  Operator_Precedence['*'] = 4;
}

static Module *Module_Ob;
static LLVMContext MyGlobalContext;
static IRBuilder<> Builder(MyGlobalContext);
static std::map<std::string, Value *> Named_Values;

Value *NumericAST::Codegen() {
  return ConstantInt::get(Type::getInt32Ty(MyGlobalContext), numeric_val);
}

Value *VariableAST::Codegen() {
  Value *V = Named_Values[Var_Name];
  return V ? V : 0;
}

Value *BinaryAST::Codegen() {
  Value *L = LHS->Codegen();
  Value *R = RHS->Codegen();
  if (L == 0 || R == 0)
    return 0;

  switch (atoi(Bin_Operator.c_str())) {
  case '+':
    return Builder.CreateAdd(L, R, "addtmp");
  case '-':
    return Builder.CreateSub(L, R, "subtmp");
  case '*':
    return Builder.CreateMul(L, R, "multmp");
  case '/':
    return Builder.CreateUDiv(L, R, "divtmp");
  default:
    return 0;
  }
}

Value *FunctionCallAST::Codegen() {
  Function *CalleeF = Module_Ob->getFunction(Function_Callee);

  std::vector<Value *> ArgsV;
  for (unsigned i = 0, e = Function_Arguments.size(); i != e; ++i) {
    ArgsV.push_back(Function_Arguments[i]->Codegen());
    if (ArgsV.back() == 0)
      return 0;
  }

  return Builder.CreateCall(CalleeF, ArgsV, "calltmp");
}

Function *FunctionDeclAST::Codegen() {
  std::vector<Type *> Integers(Arguments.size(),
                               Type::getInt32Ty(MyGlobalContext));
  FunctionType *FT =
      FunctionType::get(Type::getInt32Ty(MyGlobalContext), Integers, false);
  Function *F =
      Function::Create(FT, Function::ExternalLinkage, Func_Name, Module_Ob);

  if (F->getName() != Func_Name) {
    F->eraseFromParent();
    F = Module_Ob->getFunction(Func_Name);

    if (!F->empty())
      return 0;

    if (F->arg_size() != Arguments.size())
      return 0;
  }

  unsigned Idx = 0;
  for (Function::arg_iterator Arg_It = F->arg_begin(); Idx != Arguments.size();
       ++Arg_It, ++Idx) {
    Arg_It->setName(Arguments[Idx]);
    Named_Values[Arguments[Idx]] = Arg_It;
  }

  return F;
}

Function *FunctionDefnAST::Codegen() {
  Named_Values.clear();

  Function *TheFunction = Func_Decl->Codegen();
  if (TheFunction == 0)
    return 0;

  BasicBlock *BB = BasicBlock::Create(MyGlobalContext, "entry", TheFunction);
  Builder.SetInsertPoint(BB);

  if (Value *RetVal = Body->Codegen()) {
    Builder.CreateRet(RetVal);
    verifyFunction(*TheFunction);
    return TheFunction;
  }

  TheFunction->eraseFromParent();
  return 0;
}

static void HandleDefn() {
  if (FunctionDefnAST *F = func_defn_parser()) {
    if (Function *LF = F->Codegen()) {
    }
  } else {
    next_token();
  }
}

static void HandleTopExpression() {
  if (FunctionDefnAST *F = top_level_parser()) {
    if (Function *LF = F->Codegen()) {
    }
  } else {
    next_token();
  }
}

static void Driver() {
  while (1) {
    switch (Current_token) {
    case EOF_TOKEN:
      return;
    case ';':
      next_token();
      break;
    case DEF_TOKEN:
      HandleDefn();
      break;
    default:
      HandleTopExpression();
      break;
    }
  }
}

extern "C" double putchard(double X) {
  putchar((char)X);
  return 0;
}

int main(int argc, char *argv[]) {
  LLVMContext &Context = MyGlobalContext;
  init_precedence();

  file = fopen(argv[1], "r");
  if (file == 0) {
    printf("Could not open file\n");
  }

  next_token();
  Module_Ob = new Module("my compiler", Context);
  Driver();
  Module_Ob->print(llvm::outs(), nullptr);
  return 0;
}

$ make

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/893140.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

c语言生成.exe文件的方法

一、在Windows shell下使用gcc命令 1、需要下载获取GCC安装包 官网:MinGW-w64 - for 32 and 64 bit Windows - Browse Files at SourceForge.net 其他下载: 文件文件大小:48.0 M|https://wwnb.lanzoul.com/iIsq815lktfchttps://download.c

归并排序算法细节演示

【样例输入】 5 11 8 34 2 9 【样例输出】 2 8 9 11 34 #include<iostream> using namespace std; int n;//n个数 int data[100]; int tmp[100]; int nums 1; void ss(){cout<<endl<<"-----------------"<<endl; for(int i1;i<n;i){cou…

创建一个简单的HTML Viewer应用程序

使用wxPython和内嵌浏览器来创建一个简单的HTML Viewer应用程序。 在本篇文章中&#xff0c;我们将使用Python和wxPython模块来创建一个简单的HTML Viewer应用程序。这个应用程序可以让用户输入HTML内容&#xff0c;并在内嵌浏览器中显示该内容的效果。 准备工作 在开始之前…

Shell学习笔记之基础部分

Shell基础&#xff1a; 查看操作系统支持的shell&#xff1a; [rootrhel9 ansible]# cat /etc/shells /bin/sh /bin/bash /usr/bin/sh /usr/bin/bashShell的基本元素&#xff1a; 声明&#xff1a;声明用哪个命令解释器来解释并执行当前脚本文件中的语句&#xff0c;一般写的…

Cross-Site Scripting

文章目录 反射型xss(get)反射型xss(post)存储型xssDOM型xssDOM型xss-xxss-盲打xss-过滤xss之htmlspecialcharsxss之href输出xss之js输出 反射型xss(get) <script>alert("123")</script>修改maxlength的值 反射型xss(post) 账号admin密码123456直接登录 …

tauri-react:快速开发跨平台软件的架子,支持自定义头部UI拖拽移动和窗口阴影效果

tauri-react 一个使用 taurireacttsantd 开发跨平台软件的模板&#xff0c;支持窗口头部自定义和窗口阴影&#xff0c;不用再自己做适配了&#xff0c;拿来即用&#xff0c;非常 nice。而且已经封装好了 tauri 的 http 请求工具&#xff0c;省去很多弯路。 开原地址&#xff…

抖音短视频SEO矩阵系统源码开发

一、概述 抖音短视频SEO矩阵系统源码是一项综合技术&#xff0c;旨在帮助用户在抖音平台上创建并优化短视频内容。本文将详细介绍该系统的技术架构、核心代码、实现过程以及优化建议&#xff0c;以便读者更好地理解并应用这项技术。 二、技术架构 抖音短视频SEO矩阵系统采用前…

ai之美:探索写真照片软件的创造力

小青&#xff1a;嘿&#xff0c;小华&#xff0c;你知道最近ai艺术写真非常流行吗&#xff1f; 小华&#xff1a;真的吗&#xff1f;我还不知道呢。告诉我更多细节吧&#xff01; 小青&#xff1a;好的&#xff0c;ai艺术写真是指使用人工智能技术将照片转化为艺术作品的过程…

飞天使-k8s简单搭建(编写中)

文章目录 k8s概念安装部署无密钥配置与hosts与关闭swap开启ipv4转发安装前启用脚本开启ip_vs安装指定版本docker 安装kubeadm kubectl kubelet k8s单节点部署参考链接地址 k8s概念 K8sMaster : 管理K8sNode的。 K8sNode:具有docker环境 和k8s组件&#xff08;kubelet、k-prox…

C#小轮子:MiniExcel,快速操作Excel

文章目录 前言环境安装功能测试普通读写读新建Excel表格完全一致测试&#xff1a;成功大小写测试&#xff1a;严格大小写别名读测试&#xff1a;成功 写普通写别名写内容追加更新模板写 其它功能xlsx和CSV互转 前言 Excel的操作是我们最常用的操作&#xff0c;Excel相当于一个…

【markdown】使用 Mermaid 制作的图表和图形的一些示例

Mermaid是一种用于绘制流程图,状态图,序列图和甘特图的文本标记语言。 Mermaid的主要特点包括: 基于文本 - 使用类似Markdown的语法来描述图表,之后可以转换为SVG图表。支持流程图 - 使用图形节点和箭头来表示流程步骤和流转方向。支持状态图 - 可以绘制状态之间的转换条件。支…

【使用Zookeeper当作注册中心】自己定制负载均衡常见策略

自己定制负载均衡常见策略 一、前言随机&#xff08;Random&#xff09;策略的实现轮询&#xff08;Round Robin&#xff09;策略的实现哈希&#xff08;Hash&#xff09;策略 一、前言 大伙肯定知道&#xff0c;在分布式开发中&#xff0c;目前使用较多的注册中心有以下几个&…

Centos 8 网卡connect: Network is unreachable错误解决办法

现象1、ifconfig没有ens160配置 [testlocalhost ~]$ ifconfig lo: flags73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10<host> loop txqueuelen 1000 (Local Loopba…

css学习4(背景)

1、CSS中&#xff0c;颜色值通常以以下方式定义: 十六进制 - 如&#xff1a;"#ff0000"RGB - 如&#xff1a;"rgb(255,0,0)"颜色名称 - 如&#xff1a;"red" 2、background-image 属性描述了元素的背景图像. 默认情况下&#xff0c;背景图像进…

SaaS当然是一门好生意了啊

&#xff08;1&#xff09;SaaS关键特征 1、应用架构&#xff1a;多租户 2、部署&#xff1a;公有IaaS部署 3、商业模式&#xff1a;年度订阅续费 &#xff08;2&#xff09;用户云注册、用户在线付费 用户云注册、用户在线付费&#xff0c;站在中国乙方利益视角&#xff0c;多…

【Linux命令详解 | ssh命令】 ssh命令用于远程登录到其他计算机,实现安全的远程管理

文章标题 简介一&#xff0c;参数列表二&#xff0c;使用介绍1. 连接远程服务器2. 使用SSH密钥登录2.1 生成密钥对2.2 将公钥复制到远程服务器 3. 端口转发3.1 本地端口转发3.2 远程端口转发 4. X11转发5. 文件传输与远程命令执行5.1 文件传输5.1.1 从本地向远程传输文件5.1.2 …

WPF国际化的实现方法(WpfExtensions.Xaml)

https://blog.csdn.net/eyupaopao/article/details/120090431 resx资源文件实现 resx资源文件&#xff0c;实现的过程比第一种复杂&#xff0c;但resx文件本身编辑比较简单&#xff0c;维护起来比较方便。需要用到的框架&#xff1a;WpfExtensions.Xaml 为每种语言添加.resx资…

AI 绘画Stable Diffusion 研究(十)sd图生图功能详解-精美二维码的制作

免责声明: 本案例所用安装包免费提供&#xff0c;无任何盈利目的。 大家好&#xff0c;我是风雨无阻。 为了让大家更直观的了解图生图功能&#xff0c;明白图生图功能到底是干嘛的&#xff0c;能做什么事情&#xff1f;今天我们继续介绍图生图的实用案例-精美二维码的制作。 对…

使用dockerfile手动构建JDK11镜像运行容器并校验

Docker官方维护镜像的公共仓库网站 Docker Hub 国内无法访问了&#xff0c;大部分镜像无法下载&#xff0c;准备逐步构建自己的镜像库。【转载aliyun官方-容器镜像服务 ACR】Docker常见问题 阿里云容器镜像服务ACR&#xff08;Alibaba Cloud Container Registry&#xff09;是面…

Git多版本并行开发实践

本文目的&#xff1a; 实现多个项目同时进行的git多版本管理工作流。 名词解释&#xff1a; feature-XXXX&#xff1a;特性分支指CCS中一个项目或者一个迭代&#xff0c;在该分支上开发&#xff0c;完成后&#xff0c;合并&#xff0c;最后&#xff0c;删除该分支&#xff0c;…