LLVM IR - ›WebAssembly. Пустой модуль Wasm | пример

Я пытаюсь создать действительный файл wasm, который будет правильно понимать WebBrowser (Firefox), но я не уверен, что здесь ошибаюсь

Вот Main.ll файл

define i32 @main() {
  ret i32 42
}

Тогда я использую llc (Linux):

./llc -mtriple = wasm32-неизвестно-неизвестно -O3 -filetype = obj main.ll -o main.o

Затем я использую wasm-ld (Linux):

./wasm-ld main.o -o main.wasm --no-entry -allow-undefined

Затем я копирую main.wasm в Windows, а затем открываю эту страницу с локальным файлом:

|-- fille.html
|-- main.wasm

<div id="test">
</div>

<style>
    #test
    {
        border: 3px solid red;
        width: 100%;
        height: 100%;
    }
</style>

<script>
    fetch("main.wasm")
        .then(response => response.arrayBuffer())
        .then(bytes => WebAssembly.instantiate(bytes, {}))
        .then(results => {
          window.alert(results.instance.exports.main());
        });
</script>

Но

TypeError: results.instance.exports.main не является функцией

Что случилось?

Вот результат:

console.log (JSON.stringify (результаты));

{"module":{},"instance":{}}

Версии:

./llc --version

LLVM (http://llvm.org/):
LLVM version 10.0.0

./wasm-ld --version

LLD 10.0.0

person Axelly    schedule 15.03.2020    source источник


Ответы (1)


Причина в том, что при связывании вы не экспортировали символы.

Вы можете узнать подробности the Exports section of wasm-ld docs, но вот что они говорят о значениях по умолчанию:

При сборке исполняемого файла по умолчанию экспортируются только точка входа (_start) и символы с флагом WASM_SYMBOL_EXPORTED.

У вас есть несколько вариантов:

  1. Переименуйте main в _start - это гарантирует, что _start будет экспортирован и любые его зависимости будут правильно импортированы из среды, а не GCd вообще, как это происходит сейчас.
  2. Вызов wasm-ld с флагом --export-all - это экспортирует все символы в объектном файле. Этот вариант обычно не рекомендуется, так как вы можете предотвратить полезную оптимизацию размера и раскрыть то, что вы не собирались раскрывать, но может подойти для прототипирования.
  3. Вызов wasm-ld с помощью --export-dynamic - это экспортирует все символы, отмеченные как видимые на ИК-уровне.
  4. Явный список символов при вызове wasm-ld, например, --export=main.

Еще одно предостережение, о котором следует помнить во всех вариантах, кроме (1), заключается в том, что main обрабатывается особым образом, и с вашим текущим кодом это приведет к двум различным символам:

  1. main - автоматически сгенерированная оболочка функции с двумя аргументами для argc и argv, которая вызывает вашу функцию.
  2. __original_main - символ функции, которую вы фактически определили.

Чтобы убедиться, что вы не столкнетесь с этим, либо следуйте варианту 1 и переименуйте main в _start, который является точкой входа для Wasm и не принимает никаких параметров, либо измените подпись вашей main функции на правильную и примите оба argc и argv как в C.

Надеюсь, это все поможет вам.

person RReverser    schedule 15.03.2020
comment
@Axelly Рад, что это помогло :) - person RReverser; 17.03.2020