Fixture 69

molar mass

C · 1 functions · 4 lanes · 4 of 4 function-lanes behave identically

All 4 lanes recompile and return the same results as the original.

A chemical-formula parser: element symbols with optional multi-digit counts, looked up in a small table, accumulated as centi-atomic-mass units. Parsing plus table lookup plus accumulation in one pass.

tests/decompiler_fixtures/src/69_molar_mass.c source
#include <stdint.h>

/* A chemical-formula parser: element symbols with optional multi-digit counts,
 * looked up in a small table, accumulated as centi-atomic-mass units.  Parsing
 * plus table lookup plus accumulation in one pass. */

#define FORMULA_MAX 16

static int32_t element_mass_centi(uint8_t first, uint8_t second) {
    if (first == (uint8_t)'H' && second == 0) {
        return 101;
    }
    if (first == (uint8_t)'C' && second == 0) {
        return 1201;
    }
    if (first == (uint8_t)'N' && second == 0) {
        return 1401;
    }
    if (first == (uint8_t)'O' && second == 0) {
        return 1600;
    }
    if (first == (uint8_t)'S' && second == 0) {
        return 3207;
    }
    if (first == (uint8_t)'N' && second == (uint8_t)'a') {
        return 2299;
    }
    if (first == (uint8_t)'C' && second == (uint8_t)'l') {
        return 3545;
    }
    if (first == (uint8_t)'F' && second == (uint8_t)'e') {
        return 5585;
    }
    return -1;
}

__attribute__((noinline)) int32_t
molar_mass_centi(const uint8_t *formula, int32_t length) {
    int32_t total = 0;
    int32_t index = 0;
    if (formula == 0 || length < 0 || length > FORMULA_MAX) {
        return -1;
    }
    while (index < length) {
        uint8_t first = formula[index];
        uint8_t second = 0;
        int32_t count = 0;
        int32_t mass;
        if (first < (uint8_t)'A' || first > (uint8_t)'Z') {
            return -2;
        }
        index += 1;
        if (index < length && formula[index] >= (uint8_t)'a' &&
            formula[index] <= (uint8_t)'z') {
            second = formula[index];
            index += 1;
        }
        mass = element_mass_centi(first, second);
        if (mass < 0) {
            return -3;
        }
        while (index < length && formula[index] >= (uint8_t)'0' &&
               formula[index] <= (uint8_t)'9') {
            count = count * 10 + (int32_t)(formula[index] - (uint8_t)'0');
            if (count > 99) {
                return -4;
            }
            index += 1;
        }
        if (count == 0) {
            count = 1;
        }
        total += mass * count;
    }
    return total;
}

Recovered C

Generated by glaurung decompile --style decbench at b47f6b43. baseline.json records the result after recompiling the C and calling it beside the original with seeded inputs.

clang -O0

1/1
molar_mass_centi pass 93 lines
// glaurung: molar_mass_centi @ 0x1100
int32_t molar_mass_centi(const uint8_t * arg0, int32_t arg1) {
    extern int element_mass_centi(unsigned char, unsigned char);
    int total;
    int index;
    unsigned char first;
    unsigned char second;
    int count;
    int mass;
    signed char local_29;
    int local_4;
    int var16;
    int var25;
    int var33;
    int var38;
    total = 0;
    index = 0;
    if ((arg0 != 0)) {
        if ((0 <= (long)(arg1))) {
            if ((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16))) {
                goto L_1148;
            }
        }
    }
    local_4 = -1;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
    L_1148: ;
    goto L_114d;
    L_114d: ;
    if ((arg1 <= index)) {
        goto L_12ca;
    }
    first = arg0[index];
    second = 0;
    count = 0;
    if ((65 <= (long)(first))) {
        if ((((unsigned long)((unsigned long)(first)) == 90) | ((long)(first) < 90))) {
            goto L_1198;
        }
    }
    local_4 = -2;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
    L_1198: ;
    index = ((unsigned int)(index) + 1);
    if ((index < arg1)) {
        if ((97 <= (long)((int)((unsigned char)(arg0[index]))))) {
            var16 = (unsigned int)((unsigned char)(arg0[index]));
            if (((((unsigned long)((unsigned int)(var16)) == 122) | ((long)((int)(var16)) < 122)) != 0)) {
                second = arg0[index];
                index = ((unsigned int)(index) + 1);
            }
        }
    }
    var25 = element_mass_centi((unsigned int)((unsigned char)((first & 255))), second);
    mass = var25;
    if (((long)(mass) < 0)) {
        local_4 = -3;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    goto L_121b;
    L_121b: ;
    local_29 = 0;
    if ((index < arg1)) {
        var33 = (unsigned int)((unsigned char)(arg0[index]));
        local_29 = 0;
        if ((48 <= (long)((int)(var33)))) {
            var38 = (unsigned int)((unsigned char)(arg0[index]));
            local_29 = (((unsigned long)((unsigned int)(var38)) == 57) | ((long)((int)(var38)) < 57));
        }
    }
    if (((unsigned long)((unsigned char)((local_29 & 1))) != 0)) {
        count = ((count * 10) + (unsigned int)(((unsigned int)((unsigned char)(arg0[index])) - 48)));
        if (((((unsigned long)((unsigned int)(count)) == 99) | ((long)(count) < 99)) == 0)) {
            local_4 = -4;
            // x86-64 epilogue: restore rbp
            return (unsigned int)(local_4);
        }
        index = ((unsigned int)(index) + 1);
        goto L_121b;
    }
    if (((unsigned long)((unsigned int)(count)) == 0)) {
        count = 1;
    }
    total = ((unsigned int)(((unsigned long)((unsigned int)(mass)) * count)) + total);
    goto L_114d;
    L_12ca: ;
    local_4 = total;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
}

clang -O2

1/1
molar_mass_centi pass 201 lines
// glaurung: molar_mass_centi @ 0x1100
int32_t molar_mass_centi(const uint8_t * arg0, int32_t arg1) {
    unsigned char first;
    int mass;
    int index;
    int count;
    int total;
    unsigned char second;
    long ret;
    long t167;
    long var0;
    long var10;
    long var11;
    long var12;
    long var13;
    long var16;
    int var17;
    long var2;
    long var21;
    long var22;
    long var23;
    long var24;
    long var25;
    long var37;
    long var38;
    long var42;
    int var44;
    long var46;
    int var49;
    long var52;
    long var53;
    long var7;
    ret = 0xffffffff;
    if ((arg0 == 0)) {
        goto L_1264;
    }
    if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        goto L_1264;
    }
    if (((unsigned long)((unsigned int)(arg1)) == 0)) {
        goto L_1262;
    }
    var0 = (unsigned long)((unsigned int)(arg1));
    var2 = 0;
    var7 = 0;
    var10 = 0;
    var11 = var12;
    L_112d: ;
    var13 = (long)((int)(var10));
    first = ((var11 & -256) | (arg0[(long)((int)(var10))] & 255));
    ret = (unsigned long)((unsigned int)(((unsigned int)(first) - 91)));
    if (((unsigned long)((unsigned long)((unsigned char)((ret & 255)))) < (unsigned long)(230))) {
        goto L_1268;
    }
    var16 = (var13 + 1);
    if (((long)((int)(var16)) < (long)(arg1))) {
        var17 = (unsigned int)((unsigned char)(*(char *)(((long)arg0 + var16))));
        ret = (unsigned long)((unsigned int)((var17 - 97)));
        t167 = (ret & 255);
        var21 = (((unsigned long)(26) <= (unsigned long)((unsigned long)((unsigned char)(t167)))) ? var2 : var17);
        var16 = (unsigned long)((unsigned int)((((unsigned long)(26) <= (unsigned long)((unsigned long)((unsigned char)(t167)))) ? var16 : (unsigned long)((unsigned int)((var10 + 2))))));
        var22 = var21;
        if (((unsigned long)((unsigned char)((first & 255))) == 72)) {
            goto L_1178;
        }
        var23 = var21;
        var24 = ret;
        var25 = var16;
        goto L_1183;
    }
    var22 = 0;
    var23 = 0;
    var24 = ret;
    var25 = var16;
    if (((unsigned long)((unsigned char)((first & 255))) != 72)) {
        goto L_1183;
    }
    L_1178: ;
    var23 = var22;
    var24 = ret;
    var25 = var16;
    mass = 101;
    if (((unsigned long)((unsigned char)((var22 & 255))) == 0)) {
        goto L_1200;
    }
    L_1183: ;
    if (((unsigned long)((unsigned char)((first & 255))) == 67)) {
        mass = 1201;
        ret = var24;
        var16 = var25;
        if (((unsigned long)((unsigned char)((var23 & 255))) == 0)) {
            goto L_1200;
        }
    }
    if (((unsigned long)((unsigned char)((first & 255))) == 78)) {
        mass = 1401;
        ret = var24;
        var16 = var25;
        if (((unsigned long)((unsigned char)((var23 & 255))) == 0)) {
            goto L_1200;
        }
    }
    if (((unsigned long)((unsigned char)((first & 255))) == 79)) {
        mass = 1600;
        ret = var24;
        var16 = var25;
        if (((unsigned long)((unsigned char)((var23 & 255))) == 0)) {
            goto L_1200;
        }
    }
    if (((unsigned long)((unsigned char)((first & 255))) == 83)) {
        mass = 3207;
        ret = var24;
        var16 = var25;
        if (((unsigned long)((unsigned char)((var23 & 255))) == 0)) {
            goto L_1200;
        }
    }
    if (((unsigned long)((unsigned char)((first & 255))) == 78)) {
        mass = 2299;
        ret = var24;
        var16 = var25;
        if (((unsigned long)((unsigned char)((var23 & 255))) == 97)) {
            goto L_1200;
        }
    }
    if (((unsigned long)((unsigned char)((first & 255))) == 67)) {
        mass = 3545;
        ret = var24;
        var16 = var25;
        if (((unsigned long)((unsigned char)((var23 & 255))) == 108)) {
            goto L_1200;
        }
    }
    ret = 0xfffffffd;
    if (((unsigned long)((unsigned char)((first & 255))) != 70)) {
        goto L_1264;
    }
    mass = 0x15d1;
    if (((unsigned long)((unsigned char)((var23 & 255))) != 101)) {
        goto L_1264;
    }
    var16 = var25;
    L_1200: ;
    var37 = var16;
    var38 = (unsigned long)(first);
    if (((long)(arg1) <= (long)((int)(var16)))) {
        goto L_1240;
    }
    var42 = 0;
    index = (long)((int)(var16));
    L_1210: ;
    var44 = (unsigned int)((unsigned char)(*(char *)(((long)arg0 + index))));
    var46 = (unsigned long)((unsigned int)(index));
    if (((unsigned long)((unsigned long)((unsigned char)(((unsigned long)((unsigned int)((var44 - 48))) & 255)))) <= (unsigned long)(9))) {
        var49 = ((unsigned int)((var44 + ((unsigned long)((unsigned int)((var42 + (var42 * 4)))) * 2))) - 48);
        count = (unsigned long)((unsigned int)(var49));
        if (((((unsigned long)((unsigned int)(var49)) == 99) | ((long)((int)(var49)) < 99)) == 0)) {
            goto L_125b;
        }
        index = (index + 1);
        var42 = (unsigned long)((unsigned int)(count));
        if ((var0 != index)) {
            goto L_1210;
        }
        var42 = (unsigned long)((unsigned int)(count));
        var46 = (unsigned long)((unsigned int)(var0));
    }
    var52 = var42;
    var53 = (unsigned long)((unsigned int)(var44));
    if (((unsigned long)((unsigned int)(var42)) != 0)) {
        goto L_1245;
    }
    var37 = var46;
    var38 = (unsigned long)((unsigned int)(var44));
    L_1240: ;
    var52 = 1;
    var46 = var37;
    var53 = var38;
    L_1245: ;
    total = (var7 + (unsigned int)((var52 * mass)));
    ret = (unsigned long)((unsigned int)(total));
    var7 = (unsigned long)((unsigned int)(total));
    var10 = (unsigned long)((unsigned int)(var46));
    var11 = var53;
    if (((long)((int)(var46)) < (long)(arg1))) {
        goto L_112d;
    }
    goto L_1264;
    L_125b: ;
    ret = 0xfffffffc;
    goto L_1264;
    L_1262: ;
    ret = 0;
    L_1264: ;
    // x86-64 epilogue: tear down frame
    return ret;
    L_1268: ;
    ret = 0xfffffffe;
    goto L_1264;
}

gcc -O0

1/1
molar_mass_centi pass 77 lines
// glaurung: molar_mass_centi @ 0x11ad
int32_t molar_mass_centi(const uint8_t * arg0, int32_t arg1) {
    extern int element_mass_centi(unsigned char, unsigned char);
    int total;
    int index;
    unsigned char first;
    unsigned char second;
    int count;
    int mass;
    int var25;
    int var32;
    total = 0;
    index = 0;
    if ((arg0 != 0)) {
        if ((0 <= (long)(arg1))) {
            if ((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16))) {
                goto L_1313;
            }
        }
    }
    // x86-64 epilogue: restore rbp
    return 0xffffffff;
    L_11ef: ;
    first = arg0[index];
    second = 0;
    count = 0;
    if (((unsigned long)(64) < (unsigned long)(first))) {
        if (((unsigned long)(first) <= (unsigned long)(90))) {
            goto L_1223;
        }
    }
    // x86-64 epilogue: restore rbp
    return 0xfffffffe;
    L_1223: ;
    index = (index + 1);
    if ((index < arg1)) {
        if (((unsigned long)(96) < (unsigned long)((unsigned long)((unsigned char)(((unsigned int)((unsigned char)(arg0[index])) & 255)))))) {
            if (((unsigned long)((unsigned long)((unsigned char)(((unsigned int)((unsigned char)(arg0[index])) & 255)))) <= (unsigned long)(122))) {
                second = arg0[index];
                index = (index + 1);
            }
        }
    }
    var25 = element_mass_centi((unsigned long)((unsigned long)(first)), (unsigned long)((unsigned long)(second)));
    mass = var25;
    if ((0 <= (long)(mass))) {
        goto L_12cc;
    }
    // x86-64 epilogue: restore rbp
    return 0xfffffffd;
    L_1292: ;
    var32 = ((unsigned int)(((unsigned long)((unsigned int)(count)) << 2)) + (unsigned int)(count));
    count = ((unsigned int)(((unsigned int)((unsigned char)(((unsigned int)((unsigned char)(arg0[index])) & 255))) - 48)) + (unsigned int)(((unsigned long)((unsigned int)(var32)) + (unsigned long)((unsigned int)(var32)))));
    if (((((unsigned long)((unsigned int)(count)) == 99) | ((long)(count) < 99)) == 0)) {
        // x86-64 epilogue: restore rbp
        return 0xfffffffc;
    }
    index = (index + 1);
    L_12cc: ;
    if ((index < arg1)) {
        if (((unsigned long)(47) < (unsigned long)((unsigned long)((unsigned char)(((unsigned int)((unsigned char)(arg0[index])) & 255)))))) {
            if (((unsigned long)((unsigned long)((unsigned char)(((unsigned int)((unsigned char)(arg0[index])) & 255)))) <= (unsigned long)(57))) {
                goto L_1292;
            }
        }
    }
    if (((unsigned long)((unsigned int)(count)) == 0)) {
        count = 1;
    }
    total = (total + (unsigned int)(((unsigned long)((unsigned int)(mass)) * count)));
    L_1313: ;
    if ((index < arg1)) {
        goto L_11ef;
    }
    // x86-64 epilogue: restore rbp
    return (unsigned int)(total);
}

gcc -O2

1/1
molar_mass_centi pass 205 lines
// glaurung: molar_mass_centi @ 0x1100
int32_t molar_mass_centi(const uint8_t * arg0, int32_t arg1) {
    unsigned char first;
    int index;
    unsigned char second;
    int count;
    int total;
    long t183;
    long t184;
    long var0;
    long var1;
    long var12;
    long var13;
    long var18;
    int var19;
    long var21;
    long var23;
    long var26;
    long var28;
    long var29;
    long var34;
    long var37;
    int var40;
    int var41;
    long var43;
    long var44;
    long var45;
    long var46;
    int var47;
    long var49;
    var0 = (long)arg0;
    var1 = (unsigned long)((unsigned int)(arg1));
    if (((arg0 == 0) || ((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg1)))))) {
        goto L_12ef;
    }
    if (((unsigned long)((unsigned int)(arg1)) == 0)) {
        goto L_12e7;
    }
    var12 = 0;
    var13 = 0;
    L_112b: ;
    first = (unsigned int)((unsigned char)(*(char *)((var0 + (long)((int)(var13))))));
    if (((unsigned long)(25) < (unsigned long)((unsigned long)((unsigned char)(((unsigned long)((unsigned int)(((unsigned int)(first) - 65))) & 255)))))) {
        goto L_12d1;
    }
    index = (unsigned long)((unsigned int)((var13 + 1)));
    if ((((unsigned int)(var1) == (unsigned int)(index)) | ((long)((int)(var1)) < (long)(index)))) {
        goto L_1230;
    }
    var18 = (long)(index);
    var19 = (unsigned int)((unsigned char)(*(char *)((var0 + (long)(index)))));
    if (((unsigned long)((unsigned long)((unsigned char)(((unsigned long)((unsigned int)((var19 - 97))) & 255)))) <= (unsigned long)(25))) {
        goto L_1290;
    }
    var21 = 101;
    var23 = (unsigned long)((unsigned int)(index));
    if (((unsigned long)((unsigned char)((first & 255))) == 72)) {
        goto L_11df;
    }
    L_116b: ;
    t183 = ((unsigned long)(first) & 255);
    var26 = ((unsigned long)((unsigned char)(t183)) == 67);
    if (((unsigned long)((unsigned char)(t183)) == 67)) {
        goto L_1268;
    }
    t184 = ((unsigned long)(first) & 255);
    var28 = ((unsigned long)((unsigned char)(t184)) == 78);
    if (((unsigned long)((unsigned char)(t184)) == 78)) {
        goto L_1280;
    }
    var29 = 1;
    var23 = (unsigned long)((unsigned int)(index));
    second = 0;
    L_118a: ;
    if (((unsigned long)((unsigned char)((first & 255))) == 79)) {
        if (((unsigned long)((unsigned char)((var29 & 255))) != 0)) {
            goto L_12b0;
        }
    }
    if (((unsigned long)((unsigned char)((first & 255))) == 83)) {
        if (((unsigned long)((unsigned char)((var29 & 255))) != 0)) {
            goto L_1273;
        }
    }
    if (((unsigned long)((unsigned char)((second & 255))) == 97)) {
        if (((unsigned long)((unsigned char)((var28 & 255))) != 0)) {
            goto L_12bb;
        }
    }
    if (((unsigned long)((unsigned char)((second & 255))) == 108)) {
        if (((unsigned long)((unsigned char)((var26 & 255))) != 0)) {
            goto L_12c6;
        }
    }
    if (((unsigned long)((unsigned char)((first & 255))) != 70)) {
        goto L_12dc;
    }
    if (((unsigned long)((unsigned char)((second & 255))) != 101)) {
        goto L_12dc;
    }
    var21 = 0x15d1;
    L_11d7: ;
    if (((long)((int)(var1)) <= (long)((int)(var23)))) {
        goto L_123e;
    }
    var18 = (long)((int)(var23));
    L_11df: ;
    var34 = (var18 + var0);
    var37 = var23;
    count = 0;
    goto L_1208;
    L_11f0: ;
    count = (unsigned long)((unsigned int)(((var40 + ((unsigned long)((unsigned int)((count + (count * 4)))) * 2)) - 48)));
    if (((((unsigned long)((unsigned int)(count)) == 99) | ((long)(count) < 99)) == 0)) {
        goto L_1258;
    }
    var41 = (var37 + 1);
    var37 = (unsigned long)((unsigned int)(var41));
    var34 = (var34 + 1);
    if (((unsigned int)(var1) == (unsigned int)(var41))) {
        goto L_1248;
    }
    L_1208: ;
    var40 = (unsigned int)((unsigned char)(*(char *)((var34))));
    if (((unsigned long)((unsigned long)((unsigned char)(((unsigned long)((unsigned int)((var40 - 48))) & 255)))) <= (unsigned long)(9))) {
        goto L_11f0;
    }
    var43 = (unsigned long)((unsigned int)(var37));
    var44 = var37;
    var45 = var37;
    var46 = (unsigned long)((unsigned int)(count));
    if (((unsigned long)((unsigned int)(count)) != 0)) {
        goto L_124c;
    }
    L_121a: ;
    var47 = (var12 + var21);
    var12 = (unsigned long)((unsigned int)(var47));
    var13 = var43;
    var49 = (unsigned long)((unsigned int)(var47));
    if (((long)((int)(var44)) < (long)((int)(var1)))) {
        goto L_112b;
    }
    L_1226: ;
    return (unsigned int)(var49);
    L_1230: ;
    if (((unsigned long)((unsigned char)((first & 255))) != 72)) {
        goto L_116b;
    }
    var21 = 101;
    L_123e: ;
    var49 = (unsigned long)((unsigned int)((var12 + var21)));
    goto L_1226;
    L_1248: ;
    var45 = var37;
    var46 = (unsigned long)((unsigned int)(count));
    if (((unsigned long)((unsigned int)(count)) == 0)) {
        goto L_123e;
    }
    L_124c: ;
    var21 = (unsigned long)((unsigned int)((var21 * var46)));
    var43 = (unsigned long)((unsigned int)(var45));
    var44 = var45;
    goto L_121a;
    L_1258: ;
    return 0xfffffffc;
    L_1268: ;
    var21 = 1201;
    var23 = (unsigned long)((unsigned int)(index));
    goto L_11d7;
    L_1273: ;
    var21 = 3207;
    goto L_11d7;
    L_1280: ;
    var21 = 1401;
    var23 = (unsigned long)((unsigned int)(index));
    goto L_11d7;
    L_1290: ;
    var26 = ((unsigned long)((unsigned char)((first & 255))) == 67);
    var28 = ((unsigned long)((unsigned char)((first & 255))) == 78);
    var29 = 0;
    var23 = (unsigned long)((unsigned int)((var13 + 2)));
    second = var19;
    goto L_118a;
    L_12b0: ;
    var21 = 1600;
    goto L_11d7;
    L_12bb: ;
    var21 = 2299;
    goto L_11d7;
    L_12c6: ;
    var21 = 3545;
    goto L_11d7;
    L_12d1: ;
    var49 = 0xfffffffe;
    goto L_1226;
    L_12dc: ;
    var49 = 0xfffffffd;
    goto L_1226;
    L_12e7: ;
    var49 = 0;
    goto L_1226;
    L_12ef: ;
    var49 = 0xffffffff;
    goto L_1226;
}

← 213 fixtures