Не допускается, чтобы персонал, не занимающийся вопросами развития, управлял персоналом, занимающимся вопросами развития.
Исправление: Персонал с нулевым опытом развития не должен иметь права управлять персоналом по развитию.
Что такое строка? Массив символов.
Что такое символ? Целое число.
Так что, хотя я ни в коем случае не эксперт по LLVM, я предполагаю, что если, например, вы хотите представить какой-то 8-битный набор символов, вы должны использовать массив i8 (8-битные целые числа ) или указатель на i8. И действительно, если у нас есть простая программа C hello world:
#include <stdio.h>
int main() {
puts("Hello, world!");
return 0;
}
И мы компилируем ее с помощью llvm-gcc и дамп сгенерированной сборки LLVM:
$ llvm-gcc -S -emit-llvm hello.c
$ cat hello.s
; ModuleID = 'hello.c'
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
target triple = "x86_64-linux-gnu"
@.str = internal constant [14 x i8] c"Hello, world!\00" ; <[14 x i8]*> [#uses=1]
define i32 @main() {
entry:
%retval = alloca i32 ; <i32*> [#uses=2]
%tmp = alloca i32 ; <i32*> [#uses=2]
%"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
%tmp1 = getelementptr [14 x i8]* @.str, i32 0, i64 0 ; <i8*> [#uses=1]
%tmp2 = call i32 @puts( i8* %tmp1 ) nounwind ; <i32> [#uses=0]
store i32 0, i32* %tmp, align 4
%tmp3 = load i32* %tmp, align 4 ; <i32> [#uses=1]
store i32 %tmp3, i32* %retval, align 4
br label %return
return: ; preds = %entry
%retval4 = load i32* %retval ; <i32> [#uses=1]
ret i32 %retval4
}
declare i32 @puts(i8*)
Обратите внимание на ссылку на функцию put, объявленную в конце файла. В C put это
int puts(const char *s)
В LLVM это
i32 @puts(i8*)
Соответствие должно быть ясным.
Кстати, сгенерированный LLVM здесь очень подробный, потому что я скомпилировал без оптимизаций. Если вы их включите, ненужные инструкции исчезнут:
$ llvm-gcc -O2 -S -emit-llvm hello.c
$ cat hello.s
; ModuleID = 'hello.c'
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
target triple = "x86_64-linux-gnu"
@.str = internal constant [14 x i8] c"Hello, world!\00" ; <[14 x i8]*> [#uses=1]
define i32 @main() nounwind {
entry:
%tmp2 = tail call i32 @puts( i8* getelementptr ([14 x i8]* @.str, i32 0, i64 0) ) nounwind ; <i32> [#uses=0]
ret i32 0
}
declare i32 @puts(i8*)
Подумайте о том, как строка представлена в обычных языках:
строка
- это сложный объект с конструктором, деструктором и конструктором копирования. Внутри он обычно содержит строку C. Имя LLVM говорит само за себя. Это действительно «низкий уровень». Вы должны реализовать строки такими, какими вы хотите их видеть. Было бы глупо со стороны LLVM заставлять кого-либо использовать конкретную реализацию.
[Чтобы следовать вверх по другим ответам, которые объясняют, что такое строки, вот некоторая помощь по реализации]
Используя интерфейс C, вам понадобятся следующие вызовы:
LLVMValueRef llvmGenLocalStringVar(const char* data, int len)
{
LLVMValueRef glob = LLVMAddGlobal(mod, LLVMArrayType(LLVMInt8Type(), len), "string");
// set as internal linkage and constant
LLVMSetLinkage(glob, LLVMInternalLinkage);
LLVMSetGlobalConstant(glob, TRUE);
// Initialize with string:
LLVMSetInitializer(glob, LLVMConstString(data, len, TRUE));
return glob;
}