8000 String examples · Issue #22 · llir/llvm · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

String examples #22

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Virtual-Machine opened this issue Aug 2, 2017 · 5 comments
Closed

String examples #22

Virtual-Machine opened this issue Aug 2, 2017 · 5 comments
Labels
Milestone

Comments

@Virtual-Machine
Copy link

Could you provide an example of generating llvm ir with string usage and concatenation using the API? Your main example on the readme is great for using integer values and variables but I am struggling to convert the example to use strings or pointer values in general.

I know what I would like the ir to look like, but I am unclear how to generate the resultant ir using the API.

example:

From C:

#include <stdio.h>
#include <string.h>

int main() {
   char src[50], dest[50];

   strcpy(src,  "This is source");
   strcpy(dest, "This is destination");

   strcat(dest, src);

   printf("Final destination string : |%s|", dest);
   
   return(0);
}

To desired llvm ir:

@.str = private unnamed_addr constant [15 x i8] c"This is source\00", align 1
@.str.1 = private unnamed_addr constant [20 x i8] c"This is destination\00", align 1
@.str.2 = private unnamed_addr constant [32 x i8] c"Final destination string : |%s|\00", align 1

; Function Attrs: noinline nounwind uwtable
define i32 @main() #0 {
  %1 = alloca i32, align 4
  %2 = alloca [50 x i8], align 16
  %3 = alloca [50 x i8], align 16
  store i32 0, i32* %1, align 4
  %4 = getelementptr inbounds [50 x i8], [50 x i8]* %2, i32 0, i32 0
  %5 = call i8* @strcpy(i8* %4, i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str, i32 0, i32 0)) #3
  %6 = getelementptr inbounds [50 x i8], [50 x i8]* %3, i32 0, i32 0
  %7 = call i8* @strcpy(i8* %6, i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.str.1, i32 0, i32 0)) #3
  %8 = getelementptr inbounds [50 x i8], [50 x i8]* %3, i32 0, i32 0
  %9 = getelementptr inbounds [50 x i8], [50 x i8]* %2, i32 0, i32 0
  %10 = call i8* @strcat(i8* %8, i8* %9) #3
  %11 = getelementptr inbounds [50 x i8], [50 x i8]* %3, i32 0, i32 0
  %12 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([32 x i8], [32 x i8]* @.str.2, i32 0, i32 0), i8* %11)
  ret i32 0
}

; Function Attrs: nounwind
declare i8* @strcpy(i8*, i8*) #1

; Function Attrs: nounwind
declare i8* @strcat(i8*, i8*) #1

declare i32 @printf(i8*, ...) #2
@mewmew
Copy link
Member
mewmew commented Aug 2, 2017

Hi Darrel!

To create character arrays, set the CharArray member to true in the array constant struct.

package main

import (
	"fmt"

	"github.com/llir/llvm/ir"
	"github.com/llir/llvm/ir/constant"
	"github.com/llir/llvm/ir/types"
)

func main() {
	// Convenience types and values.
	i32 := types.I32
	i8 := types.I8
	i8x50 := types.NewArray(50, i8)
	i8ptr := types.NewPointer
8000
(i8)
	zero := constant.NewInt(i32, 0)
	// Function declarations.
	m := ir.NewModule()
	strcpy := m.NewFunc("strcpy", i8ptr, ir.NewParam("dst", i8ptr), ir.NewParam("src", i8ptr))
	strcat := m.NewFunc("strcat", i8ptr, ir.NewParam("dst", i8ptr), ir.NewParam("src", i8ptr))
	printf := m.NewFunc("printf", i32, ir.NewParam("format", i8ptr))
	printf.Sig.Variadic = true
	// Global variables.
	str := m.NewGlobalDef(".str", constant.NewCharArrayFromString("This is source\x00"))
	str.Immutable = true
	strElemType := str.Type().(*types.PointerType).ElemType
	str1 := m.NewGlobalDef(".str.1", constant.NewCharArrayFromString("This is destination\x00"))
	str1.Immutable = true
	str1ElemType := str1.Type().(*types.PointerType).ElemType
	str2 := m.NewGlobalDef(".str.2", constant.NewCharArrayFromString("Final destination string : |%s|\x00"))
	str2.Immutable = true
	str2ElemType := str2.Type().(*types.PointerType).ElemType
	// Function definitions.
	f := m.NewFunc("main", i32)
	entry := f.NewBlock("")
	tmp1 := entry.NewAlloca(i32)
	tmp2 := entry.NewAlloca(i8x50)
	tmp3 := entry.NewAlloca(i8x50)
	entry.NewStore(zero, tmp1)
	tmp4 := entry.NewGetElementPtr(i8x50, tmp2, zero, zero)
	entry.NewCall(strcpy, tmp4, constant.NewGetElementPtr(strElemType, str, zero, zero))
	tmp6 := entry.NewGetElementPtr(i8x50, tmp3, zero, zero)
	entry.NewCall(strcpy, tmp6, constant.NewGetElementPtr(str1ElemType, str1, zero, zero))
	tmp8 := entry.NewGetElementPtr(i8x50, tmp3, zero, zero)
	tmp9 := entry.NewGetElementPtr(i8x50, tmp2, zero, zero)
	entry.NewCall(strcat, tmp8, tmp9)
	tmp11 := entry.NewGetElementPtr(i8x50, tmp3, zero, zero)
	entry.NewCall(printf, constant.NewGetElementPtr(str2ElemType, str2, zero, zero), tmp11)
	entry.NewRet(zero)
	// Print module to standard output.
	fmt.Println(m)
}

Produces the following LLVM IR output:

@.str = constant [15 x i8] c"This is source\00"
@.str.1 = constant [20 x i8] c"This is destination\00"
@.str.2 = constant [32 x i8] c"Final destination string : |%s|\00"

declare i8* @strcpy(i8* %dst, i8* %src)

declare i8* @strcat(i8* %dst, i8* %src)

declare i32 @printf(i8* %format, ...)

define i32 @main() {
0:
	%1 = alloca i32
	%2 = alloca [50 x i8]
	%3 = alloca [50 x i8]
	store i32 0, i32* %1
	%4 = getelementptr [50 x i8], [50 x i8]* %2, i32 0, i32 0
	%5 = call i8* @strcpy(i8* %4, i8* getelementptr ([15 x i8], [15 x i8]* @.str, i32 0, i32 0))
	%6 = getelementptr [50 x i8], [50 x i8]* %3, i32 0, i32 0
	%7 = call i8* @strcpy(i8* %6, i8* getelementptr ([20 x i8], [20 x i8]* @.str.1, i32 0, i32 0))
	%8 = getelementptr [50 x i8], [50 x i8]* %3, i32 0, i32 0
	%9 = getelementptr [50 x i8], [50 x i8]* %2, i32 0, i32 0
	%10 = call i8* @strcat(i8* %8, i8* %9)
	%11 = getelementptr [50 x i8], [50 x i8]* %3, i32 0, i32 0
	%12 = call i32 (i8*, ...) @printf(i8* getelementptr ([32 x i8], [32 x i8]* @.str.2, i32 0, i32 0), i8* %11)
	ret i32 0
}

Edit: the code example was updated to version v0.3.6 of llir/llvm on 2024-03-09.

@Virtual-Machine
Copy link
Author
Virtual-Machine commented Aug 4, 2017

Wow! Thank you so much! You went above and beyond here! Can't wait to experiment with this on the weekend.

The newCharArray function was exactly what I was missing!

PS. Kudos on all your hard work with this library.

@mewmew
Copy link
Member
mewmew commented Aug 4, 2017

Wow! Thank you so much! You went above and beyond here! Can't wait to experiment with this on the weekend.

The newCharArray function was exactly what I was missing!

PS. Kudos on all your hard work with this library.

Glad to see others eager to play with LLVM IR :)

If you play with something fun, would be lovely to check out your git repo later!

Happy hacking!

Cheers /u

@ghost
Copy link
ghost commented Mar 7, 2024

The code shown above doesn't compile in the latest version. Could it be possible to have a revision of the code? Especially the newCharArray.

@mewmew
Copy link
Member
mewmew commented Mar 9, 2024

Hi @dequeb!

Happy to see you are exploring the world of LLVM : )

I've updated the code example in #22 (comment) so now it should work with the latest version of llir/llvm (v0.3.6 at time of writing).

In particular, there is now a function called constant.NewCharArrayFromString that will create a character array constant given a Go string.

Happy coding!

Cheers,
Robin

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants
0