Du befindest dich hier: FSI Informatik » Prüfungsfragen und Altklausuren » Hauptstudiumsprüfungen » Lehrstuhl 2 » CB3 vom 14.04.2025

CB3 vom 14.04.2025

  • Prüfer: David Schwarzbeck, Prof. Philippsen
  • Raum: Büro von Prof. Philippsen
  • Note: 1.0

Gedächtnisprotokoll

Praktikum

Was haben wir im Blockpraktikum gemacht?

TVM Interpreter und JIT in unterschiedlichen Stufen

Wieso TVM und nicht zB e2-Ast?

AST kompliziert, viele Fälle für Traversierung x86 etc unschön weil zB self-modifying code

Was macht der Interpreter?

  • Große Schleife
  • Instruktion lesen
  • Großes Switch-Case
  • Ausführen

Wie kann man das schneller machen?

Durchfädeln (erklärt)

Wieso haben wir zwei Stacks?

Interpreter hat einen, Interpretier Code auch

Was passiert dann mit Argumenten, wo landen die?

Erstmal nur im Interpreter für FFI, landen dann als lokale Variablen auf dem emulierten Stack

Wie geht das alles mit nem JIT schneller?

Erstmal Stackvergabe

Was passiert bei Calls?

Trampolin, Behandlung von Argumenten (prepare_call), gff Check ob native-code schon vorhanden

Aber alles aufm Stack ist doch uncool

Registervergabe, mit SCC und Linear Scan

Hab Kontrollflussgraph bekommen (bzw dann nach Schritt 1 den umgedrehten), einmal Kosarajus für SCCs durchexerzieren (linear scan wurde ich nicht gefragt)

Lebensspannen gehen dann von?

SCC-Graph topologisch sortieren, von niedrigster verwendeter Nummer bis höchster

Aber ein Kontrollflussgraph hat doch Zyklen!

Ja, aber die haben wir mit den SCCs eliminiert, bleibt nur noch ein DAG.

Linker/Lader

e2 hat jetzt ne externe stdlib: was passiert bei statischem Binden?

Objektdateien haben Symboltabelle für unaufgelöste Symbole (zB printf). Linker klebt Objects aneinander und löst dabei Symbole auf.

Wie machen wir das wenn wir nicht jedes mal executable neu bauen wollen?

Shared Libs

Was sind die Unterschiede von static und dynamic shared Libs?

static: Adressraum bekannt, gff Relokation (wie das funktioniert wollten sie sehr genau wissen) dynamic: loader setzt Adressen, PIC wichtig damit lib überall liegen kann. Zugriffe über GOT und PLT.

LLVM

Was ist LLVM?

IR und ganze Toolchain

Was ist cool daran?

Müssen nur ein Frontend bauen

Und am LLVM-IR direkt? was macht den besonders?

  • self-contained, keine Abhängigkeit an Frontend-Strukturen (vgl Gimple)
  • unbegrenzt viele Register
  • in SSA-Form
  • typisiert
  • (kein implizites Fallthrough) wusste ich nicht mehr

Aber selber SSA bauen ist doch blöd!

mem2reg, man macht selber nur stackbasiert, da muss man kein SSA einhalten

gibt Code (ca)

struct B {
    double arr[10];
};
 
struct A {
    int foo;
    struct B* bar;
};
 
double bazz(struct A* p) {
    return p->foo + p->bar->arr[3];
}
define double @bazz(ptr %0) {
  %2 = load i32, ptr %0, align 8
  %3 = sitofp i32 %2 to double
  %4 = getelementptr %struct.A, ptr %0, i64 0, i32 1
  %5 = load ptr, ptr %4, align 8
  %6 = getelementptr [10 x double], ptr %5, i64 0, i64 3
  %7 = load double, ptr %6, align 8
  %8 = fadd double %7, %3
  ret double %8
}

Guck mal hier, was passiert hier? grade bei getelementptr.

Unbegrenzt Argumente, cool für mehrdimensionale Arrays. Hier für structs

Und warum wird da so oft dereferenziert?

getelementptr gibt nen Pointer auf das indizierte Datum, muss dann dereferenziert werden.

Bewertung

Angekreidet wurden fehlende/falsche Fachbegriffe und dass ich nicht mehr wusste, dass LLVM-IR keine impliziten Fallthroughs hat. „Wie schlimm waren die Fehler? Nicht schlimm genug um was an der Note zu ändern.“