Связывание с кодом языка ассемблера из Rust вызывает массу ошибок компоновщика - PullRequest
0 голосов
/ 13 июля 2020

Итак, я написал функцию для сортировки десятичных чисел в Assembly (на самом деле в Arithmeti c Expression Compiler , но выводит сборку) с именем hybrid_sort (если важно, код сборки имеется здесь ). Пример программы на C ++, в которой он используется, выглядит следующим образом:

/*
 * Dakle, ovo ce biti omotac oko "hybrid_sort.aec" napisan u C++-u.
 * "hybrid_sort.aec" sam po sebi nije program koji se moze pokrenuti,
 * i zato cemo od C++ compilera (u ovom slucaju, GCC-a) traziti da
 * napravi program unutar kojeg ce se "hybrid_sort.aec" moci pokrenuti,
 * i, po mogucnosti, koji ce olaksati da ga testiramo. Drugim rijecima,
 * ovo je program s kojim se "hybrid_sort.aec" moze staticki linkirati.
 * */
#include <algorithm>
#include <chrono>
#include <fstream>
#include <iostream>
#include <iterator>
#include <random>

namespace AEC { // Da se razlikuju AEC-ove varijable od C++-ovih.
extern "C" {    // Za GNU Linker (koji se dobije uz Linux i koristi ga GCC), AEC
                // jezik je dijalekt C-a, a moj compiler je C compiler.
float result, originalni_niz[1 << 16], kopija_originalnog_niza[1 << 16],
    pomocni_niz[1 << 16], i, gdje_smo_u_prvom_nizu, gdje_smo_u_drugom_nizu,
    gornja_granica, donja_granica, sredina_niza,
    stog_sa_sredinama_niza[1 << 10], stog_s_donjim_granicama[1 << 10],
    stog_s_gornjim_granicama[1 << 10], vrh_stoga, pomocna_varijabla_za_zamijenu,
    gdje_je_pivot, j, pivot, koliko_usporedbi_ocekujemo_od_QuickSorta,
    koliko_usporedbi_ocekujemo_od_MergeSorta, razvrstanost,
    Eulerov_broj_na_koju_potenciju, polinom_pod_apsolutnom,
    razvrstanost_na_potenciju[8],
    broj_vec_poredanih_podniza = 0, broj_obrnuto_poredanih_podniza = 0,
    broj_pokretanja_MergeSorta = 0,
    broj_pokretanja_QuickSorta =
        0; // GNU linker omogucuje da se varijable ne deklariraju ne samo u
           // razlicitim datotekama, nego i u razlicitim jezicima.
void hybrid_sort(); //".global hybrid_sort" iz "hybrid_sort.aec". U C++-u ga
                    // morate deklarirati da biste ga mogli koristiti. C++ nije
                    // kao JavaScript ili AEC u tom pogledu, C++ pokusava
                    // pronaci krivo natipkana imena varijabli i funkcija vec za
                    // vrijeme compiliranja.
}
} // namespace AEC

int main() {
  std::cout << "Unesite koliko zelite da generirani niz bude dugacak."
            << std::endl;
  int n;
  std::cin >> n;
  auto distribution = std::uniform_real_distribution<float>(-n, n);
  auto generator =
      std::default_random_engine(); // Moramo paziti da se generator
                                    // pseudo-nasumicnih brojeva inicijalizira
                                    // samo jednom, inace ce na Linuxu
                                    // generirati obrnuto sortirani niz (a ne
                                    // nasumicno poredan). To su nam spomenuli
                                    // na fakultetu, no ja to nisam uzeo
                                    // ozbiljno, pa sam se sada opekao.
  std::cout << "Generiram niz od " << n << " nasumicnih decimalnih brojeva..."
            << std::endl;
  std::generate_n(
      &AEC::originalni_niz[0], n,
      [&]() -> float { // C++-ove lambda funkcije, GCC ih podrzava od 2007, a
                       // komercijalni compileri jos od ranije. Nadajmo se da
                       // netko nece pokusati ukucati ovaj program u arhajski
                       // C++ compiler.
        return distribution(generator);
      });
  std::copy_n(&AEC::originalni_niz[0], n, &AEC::kopija_originalnog_niza[0]);
  AEC::gornja_granica = n;
  AEC::donja_granica = 0;
  AEC::vrh_stoga = -1;
  std::cout << "Pokrecem potprogram u AEC-u..." << std::endl;
  auto prvoVrijeme = std::chrono::high_resolution_clock::now();
  AEC::hybrid_sort();
  auto drugoVrijeme = std::chrono::high_resolution_clock::now();
  std::cout << "Potprogram u AEC-u je zavrsio." << std::endl;
  std::cout
      << "Detektirao je " << AEC::broj_vec_poredanih_podniza
      << " vec poredanih podnizova,\n"
      << AEC::broj_obrnuto_poredanih_podniza << " obrnuto poredanih podniza,\n"
      << AEC::broj_pokretanja_MergeSorta
      << " priblizno poredanih podnizova (pogodnih za MergeSort)\n i "
      << AEC::broj_pokretanja_QuickSorta
      << " nasumicno ispremjestanih podnizova.\nPokrecem C++-ov std::sort..."
      << std::endl;
  auto treceVrijeme = std::chrono::high_resolution_clock::now();
  std::sort(&AEC::kopija_originalnog_niza[0], &AEC::kopija_originalnog_niza[n]);
  auto cetvrtoVrijeme = std::chrono::high_resolution_clock::now();
  if (!std::equal(&AEC::originalni_niz[0], &AEC::originalni_niz[n],
                  &AEC::kopija_originalnog_niza[0])) {
    std::cout << "C++-ov std::sort nije dobio isti rezultat!" << std::endl;
    std::ofstream AECovRezultat("AECresult.txt");
    std::ofstream CPPovRezultat("CPPresult.txt");
    if (!AECovRezultat || !CPPovRezultat) {
      std::cout << "Ne mogu otvoriti datoteke za ispis rezultata!" << std::endl;
      return 2;
    }
    AECovRezultat << n << std::endl;
    CPPovRezultat << n << std::endl;
    std::copy_n(&AEC::originalni_niz[0], n,
                std::ostream_iterator<float>(AECovRezultat, "\n"));
    std::copy_n(&AEC::kopija_originalnog_niza[0], n,
                std::ostream_iterator<float>(CPPovRezultat, "\n"));
    AECovRezultat.close();
    CPPovRezultat.close();
    std::cout
        << "Rezultati su spremljeni u \"AECresult.txt\" i \"CPPresult.txt\""
        << std::endl;
    return 1;
  }
  std::cout << "C++-ov std::sort dobio je isti rezultat." << std::endl;
  std::cout << "C++-ov std::sort vrtio se "
            << (cetvrtoVrijeme - treceVrijeme).count()
            << " procesorskih taktova." << std::endl;
  std::cout << "AEC-ov hybrid_sort vrtio se "
            << (drugoVrijeme - prvoVrijeme).count() << " procesorskih taktova."
            << std::endl;
  return 0;
}

Я попытался создать программу на Rust, которая его вызывает. Вот main.rs:

#[link(name = "hybrid_sort", kind = "static")]
mod aec {
    extern "C" {
        pub static mut originalni_niz: [f32; 65000];
        pub static mut pomocni_niz: [f32; 65000];
        pub static mut stog_sa_sredinama_niza: [f32; 1000];
        pub static mut stog_s_donjim_granicama: [f32; 1000];
        pub static mut stog_s_gornjim_granicama: [f32; 1000];
        pub static mut razvrstanost_na_potenciju: [f32; 8];
        pub static mut result: f32;
        pub static mut i: f32;
        pub static mut gdje_smo_u_prvom_nizu: f32;
        pub static mut gdje_smo_u_drugom_nizu: f32;
        pub static mut gornja_granica: f32;
        pub static mut donja_granica: f32;
        pub static mut sredina_niza: f32;
        pub static mut vrh_stoga: f32;
        pub static mut pomocna_varijabla_za_zamijenu: f32;
        pub static mut gdje_je_pivot: f32;
        pub static mut j: f32;
        pub static mut pivot: f32;
        pub static mut koliko_usporedbi_ocekujemo_od_QuickSorta: f32;
        pub static mut koliko_usporedbi_ocekujemo_od_MergeSorta: f32;
        pub static mut razvrstanost: f32;
        pub static mut Eulerov_broj_na_koju_potenciju: f32;
        pub static mut polinom_pod_apsolutnom: f32;
        pub static mut broj_vec_poredanih_podniza: f32;
        pub static mut broj_obrnuto_poredanih_podniza: f32;
        pub static mut broj_pokretanja_MergeSorta: f32;
        pub static mut broj_pokretanja_QuickSorta: f32;
        pub fn hybrid_sort();
    }
}

fn main() {
    unsafe {
        for i in 0..10 {
            aec::originalni_niz[i] = (10 - i) as f32;
        }
        aec::gornja_granica = 10.;
        aec::donja_granica = 0.;
        aec::hybrid_sort();
        for i in 0..10 {
            println!("{}", aec::originalni_niz[i]);
        }
    }
}

Я ожидал, что он выведет:

1
2
3
4
5
6
7
8
9
10

Вот build.rs:

extern crate cc;

fn main() {
    cc::Build::new()
        .file("src/hybrid_sort.s")
        .compile("hybrid_sort");
}

Однако, когда я запускаю cargo build, у меня такая ошибка:

error: linking with `cc` failed: exit code: 1
  |
  = note: "cc" "-Wl,--as-needed" "-Wl,-z,noexecstack" "-m64" "-L" "/home/teo.samarzija/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "/home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/deps/algorithms_by_length-17c6558ebb3996a0.1fz15oxpkgtpgr14.rcgu.o" "/home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/deps/algorithms_by_length-17c6558ebb3996a0.1wwvstjn4dyc3alz.rcgu.o" "/home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/deps/algorithms_by_length-17c6558ebb3996a0.1yxj24e45v6q9q86.rcgu.o" "/home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/deps/algorithms_by_length-17c6558ebb3996a0.2mvtt0813pf07pog.rcgu.o" "/home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/deps/algorithms_by_length-17c6558ebb3996a0.2umen39fhcwjmc0z.rcgu.o" "/home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/deps/algorithms_by_length-17c6558ebb3996a0.3091dfbqk4lshnol.rcgu.o" "/home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/deps/algorithms_by_length-17c6558ebb3996a0.35ep7euvsenolvvb.rcgu.o" "/home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/deps/algorithms_by_length-17c6558ebb3996a0.42y3nx5hyg9yjwwt.rcgu.o" "/home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/deps/algorithms_by_length-17c6558ebb3996a0.495yr540a19kuq1o.rcgu.o" "/home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/deps/algorithms_by_length-17c6558ebb3996a0.4aci444gs0pfr5mo.rcgu.o" "/home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/deps/algorithms_by_length-17c6558ebb3996a0.56j8cnoxsa6jrgia.rcgu.o" "/home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/deps/algorithms_by_length-17c6558ebb3996a0.58nstkh897vbl3yr.rcgu.o" "/home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/deps/algorithms_by_length-17c6558ebb3996a0.h0bm2f7ve74u4yg.rcgu.o" "/home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/deps/algorithms_by_length-17c6558ebb3996a0.k67895wnew0zyg9.rcgu.o" "/home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/deps/algorithms_by_length-17c6558ebb3996a0.p5p3jfl4d3vuwrj.rcgu.o" "-o" "/home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/deps/algorithms_by_length-17c6558ebb3996a0" "/home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/deps/algorithms_by_length-17c6558ebb3996a0.349a1ajb22z1v56x.rcgu.o" "-Wl,--gc-sections" "-pie" "-Wl,-zrelro" "-Wl,-znow" "-nodefaultlibs" "-L" "/home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/deps" "-L" "/home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/build/algorithms_by_length-ad934eefb132b896/out" "-L" "/home/teo.samarzija/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-Wl,-Bstatic" "-Wl,--whole-archive" "-lhybrid_sort" "-Wl,--no-whole-archive" "-Wl,--start-group" "/home/teo.samarzija/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-dd4752c70d4ce71d.rlib" "/home/teo.samarzija/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libpanic_unwind-e04840eda0100e05.rlib" "/home/teo.samarzija/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libunwind-16bfb4d182748e63.rlib" "/home/teo.samarzija/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liblibc-185d9b81685a2f08.rlib" "/home/teo.samarzija/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc-4806247fe4c34e64.rlib" "/home/teo.samarzija/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-879310dc3b96af61.rlib" "-Wl,--end-group" "/home/teo.samarzija/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-d0572f7a936161bf.rlib" "-Wl,-Bdynamic" "-ldl" "-lrt" "-lpthread" "-lgcc_s" "-lc" "-lm" "-lrt" "-lpthread" "-lutil" "-lutil"
  = note: /usr/local/bin/ld: /home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/build/algorithms_by_length-ad934eefb132b896/out/libhybrid_sort.a(hybrid_sort.o): relocation R_X86_64_32S against undefined symbol `gornja_granica' can not be used when making a PIE object; recompile with -fPIE
          /usr/local/bin/ld: /home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/deps/algorithms_by_length-17c6558ebb3996a0.58nstkh897vbl3yr.rcgu.o: in function `algorithms_by_length::main':
          /home/teo.samarzija/Documents/debug/algorithms_by_length/src/main.rs:(.text._ZN20algorithms_by_length4main17h3070ff3b86a94a98E+0xb0): undefined reference to `donja_granica'
          /usr/local/bin/ld: /home/teo.samarzija/Documents/debug/algorithms_by_length/src/main.rs:(.text._ZN20algorithms_by_length4main17h3070ff3b86a94a98E+0xb7): undefined reference to `gornja_granica'
          /usr/local/bin/ld: /home/teo.samarzija/Documents/debug/algorithms_by_length/src/main.rs:(.text._ZN20algorithms_by_length4main17h3070ff3b86a94a98E+0x14c): undefined reference to `originalni_niz'
          /usr/local/bin/ld: /home/teo.samarzija/Documents/debug/algorithms_by_length/src/main.rs:(.text._ZN20algorithms_by_length4main17h3070ff3b86a94a98E+0x2aa): undefined reference to `originalni_niz'
          collect2: error: ld returned 1 exit status

Есть идеи, что происходит?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...