Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/svg/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Llvm 需要关于写通行证的见解吗_Llvm_Llvm Clang_Llvm Ir - Fatal编程技术网

Llvm 需要关于写通行证的见解吗

Llvm 需要关于写通行证的见解吗,llvm,llvm-clang,llvm-ir,Llvm,Llvm Clang,Llvm Ir,对于我的源代码,我有以下IR: ; ModuleID = '<stdin>' @.str = private unnamed_addr constant [9 x i8] c"SOME_ENV_VAR\00", align 1 @.str1 = private unnamed_addr constant [26 x i8] c"Need to set $ENV_Variable.\0A\00", align 1 ; Function Attrs: nounwind define

对于我的源代码,我有以下IR:

; ModuleID = '<stdin>'


@.str = private unnamed_addr constant [9 x i8] c"SOME_ENV_VAR\00", align 1
@.str1 = private unnamed_addr constant [26 x i8] c"Need to set $ENV_Variable.\0A\00", align 1

; Function Attrs: nounwind
define void @foo(i8* %bar) #0 {
entry:
  %bar.addr = alloca i8*, align 4
  %baz = alloca i8*, align 4
  store i8* %bar, i8** %bar.addr, align 4
  %call = call i8* @getenv(i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0)) #2
  store i8* %call, i8** %baz, align 4
  %0 = load i8** %baz, align 4
  %cmp = icmp eq i8* %0, null
  br i1 %cmp, label %if.then, label %if.else

if.then:                                          ; preds = %entry
  %call1 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([26 x i8]* @.str1, i32 0, i32 0))
  br label %if.end

if.else:                                          ; preds = %entry
  %1 = load i8** %bar.addr, align 4
  %2 = load i8** %baz, align 4
  %call2 = call i8* @strcpy(i8* %1, i8* %2) #2
  br label %if.end

if.end:                                           ; preds = %if.else, %if.then
  ret void
}

; Function Attrs: nounwind
declare i8* @getenv(i8*) #0

declare i32 @printf(i8*, ...) #1

; Function Attrs: nounwind
declare i8* @strcpy(i8*, i8*) #0
;ModuleID=''
@.str=private unnamed_addr常量[9 x i8]c“SOME_ENV_VAR\00”,对齐1
@.str1=private unnamed_addr常量[26 x i8]c“需要设置$ENV_变量。\0A\00”,对齐1
; 函数属性:nounwind
定义void@foo(i8*%bar)#0{
条目:
%bar.addr=alloca i8*,对齐4
%baz=alloca i8*,对齐4
存储i8*%bar,i8**%bar.addr,对齐4
%call=call i8*@getenv(i8*getelementptr inbounds([9 x i8]*@.str,i32 0,i32 0))#2
存储i8*%呼叫,i8**%baz,对齐4
%0=负载i8**%baz,对齐4
%cmp=icmp eq i8*%0,空
br i1%cmp,标签%if.then,标签%if.else
if.then:;preds=%entry
%call1=calli32(i8*,…)*@printf(i8*getelementptr inbounds([26 x i8]*@.str1,i32 0,i32 0))
br标签%if.end
if.else:;preds=%entry
%1=负载i8**%bar.addr,对齐4
%2=负载i8**%baz,对齐4
%call2=调用i8*@strcpy(i8*%1,i8*%2)#2
br标签%if.end
if.end:;preds=%if.else,%if.then
ret void
}
; 函数属性:nounwind
声明i8*@getenv(i8*)#0
声明i32@printf(i8*,…)#1
; 函数属性:nounwind
声明i8*@strcpy(i8*,i8*)#0
我打算编写一个过程,它在编译时(使用LLVM)生成位代码,其中对strcpy(dest,src)的调用被strncpy(dest,src,n)替换

到目前为止,我已经编写了以下代码:

#include <stdlib.h>
#include <stdio.h>
#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/IR/IRBuilder.h"

using namespace llvm;
namespace
{
Module* makeLLVMModule() {


    Module* mod = new Module(llvm::StringRef("CustomPass"),getGlobalContext());

    Constant* c = mod->getOrInsertFunction(llvm::StringRef("foo"),Type::getInt32Ty(getGlobalContext()),NULL); 

    Function* foo = cast<Function>(c);
    Function::arg_iterator args =foo->arg_begin();
    Value* bar = args++;

    BasicBlock* Entry = BasicBlock::Create(getGlobalContext(),llvm::Twine("Entry"), foo);
    BasicBlock* False = BasicBlock::Create(getGlobalContext(),llvm::Twine("False"), foo);
    BasicBlock* True = BasicBlock::Create(getGlobalContext(),llvm::Twine("True"), foo);

    char* pPath;
    pPath = getenv("SOME_ENV_VAR");

    IRBuilder<> builder(Entry);
    Value* envVarDoesntExist = builder.CreateICmpEQ(llvm::StringRef(pPath),Constant::getNullValue(Value),llvm::Twine("temp"));
    //---1
    builder.CreateCondBr(envVarDoesntExist, False, True);

    builder.SetInsertPoint(True);
    builder.CreateCall3(strncpy,bar,llvm::StringRef(pPath),45,llvm::Twine("temp"));
    //---2 

    builder.SetInsertPoint(False);
    builder.CreateCall(printf,llvm::StringRef("Need to set $ENV_Variable.\n"),llvm::Twine("temp"));
    //---1
    return mod;        

    }

}

char funcP::ID = 0;
static RegisterPass<funcP> X("funcp", "funcP", false, false);
#包括
#包括
#包括“llvm/Pass.h”
#包括“llvm/IR/Function.h”
#包括“llvm/Support/raw_ostream.h”
#包括“llvm/IR/Module.h”
#包括“llvm/PassManager.h”
#包括“llvm/Analysis/Verifier.h”
#包括“llvm/Assembly/PrintModulePass.h”
#包括“llvm/IR/IRBuilder.h”
使用名称空间llvm;
名称空间
{
模块*makeLLVMModule(){
Module*mod=new模块(llvm::StringRef(“CustomPass”),getGlobalContext());
常量*c=mod->getOrInsertFunction(llvm::StringRef(“foo”),Type::getInt32Ty(getGlobalContext()),NULL);
函数*foo=cast(c);
函数::arg_迭代器args=foo->arg_begin();
值*bar=args++;
BasicBlock*Entry=BasicBlock::Create(getGlobalContext(),llvm::Twine(“Entry”),foo);
BasicBlock*False=BasicBlock::Create(getGlobalContext(),llvm::Twine(“False”),foo);
BasicBlock*True=BasicBlock::Create(getGlobalContext(),llvm::Twine(“True”),foo);
char*pPath;
pPath=getenv(“某些环境变量”);
建造商(入口);
Value*envvardoesntextest=builder.CreateICmpEQ(llvm::StringRef(pPath),Constant::getNullValue(Value),llvm::Twine(“temp”);
//---1
CreateCondBr(envvardoesntextest,False,True);
builder.SetInsertPoint(真);
CreateCall3(strncpy,bar,llvm::StringRef(pPath),45,llvm::Twine(“temp”);
//---2 
builder.SetInsertPoint(假);
CreateCall(printf,llvm::StringRef(“需要设置$ENV_变量。\n”)、llvm::Twine(“temp”);
//---1
返回模式;
}
}
char funcP::ID=0;
静态寄存器类X(“funcp”、“funcp”、false、false);
  • From--1:如何将llvm::StringRef转换为Value*
  • From---2:如何将char*转换为Value*
  • Constant::getNullValue(Value)
    是否可以用于获取空值
  • 我打算编写一个pass,当编译(使用LLVM)时,它将生成位代码,其中对strcpy(dest,src)的调用将替换为strncpy(dest,src,n)

    然后,您需要做的是找到call指令并对其进行更改。不需要重新创建整个流,它已经存在于源代码中

    您需要做的就是,并且是一个,被调用方的名称是strcpy,然后为新函数创建一条新的调用指令,然后将旧指令与新指令一起创建

    此外,在您的代码中,编译器中的值(例如
    45
    和所有
    StringRef
    s)与正在处理的代码中的值(其中一个子类型
    llvm::Value
    的实例)之间似乎存在一些根本性的误解。具体地说,您不能仅将
    45
    用作正在处理的代码中的函数的参数-您必须从该数字开始,然后才能使用该常数


    最后一个注意事项-您可以从
    const char*
    调用
    StringRef
    ,您不需要到处显式调用
    StringRef
    的构造函数

    您在这里有多个错误,但除此之外,您还编写了pass的目标是“将对strcpy(dest,src)的调用替换为strncpy(dest,src,n)”。但这根本不是您想要做的——您正在尝试创建整个流(检查env var,基于它的分支,并插入对printf或strncpy的调用)。你能澄清一下这个过程的目标是什么吗?写这个过程背后的想法是确保调用strncpy()而不是strcpy()-即,每当调用foo()时。我不应该创建一个新的流吗?@Oak我是LLVM的新手,如有任何帮助,将不胜感激。我不确定我是否做了正确的事情,即使如此,我仍在努力解决这些概念。如果有另一种方法可以让我得到预期的结果,那么知道如何去做会很有帮助。