ir.c
// When compiled with Position Independent Code (PIC) , all accesses to global objects
// go through a Global Offset Table (GOT). The GOT table has pointers to the globals.
// Any load/save must first load a pointer to the global object from the GOT and use
// that rather than going directly to memory.
When compiled with Position Independent Code (PIC) , all accesses to global objects
go through a Global Offset Table (GOT). The GOT table has pointers to the globals.
Any load/save must first load a pointer to the global object from the GOT and use
that rather than going directly to memory.
When compiled with Position Independent Code ( PIC ) all accesses to global objects go through a Global Offset Table ( GOT ) . The GOT table has pointers to the globals . Any load / save must first load a pointer to the global object from the GOT and use that rather than going directly to memory .
void add_PIC_load_and_saves(Function *function) {
    if (!opt_PIC) return;
    for (Tac *tac = function->ir; tac; tac = tac->next) {
        if (tac->dst && tac->dst->global_symbol && tac->operation != IR_MOVE)
            panic("Unexpected global_symbol in dst");
        if (tac->src1 && tac->src1->global_symbol
                && tac->operation != IR_MOVE
                && tac->operation != IR_CALL
                && tac->operation != IR_ADDRESS_OF
                && tac->operation != IR_DECL_LOCAL_COMP_OBJ)
            panic("Unexpected operation for global_symbol in src1: %d", tac->operation);
        if (tac->src2 && tac->src2->global_symbol)
            panic("Unexpected operation for global_symbol in src2: %d", tac->operation);
        if (tac->dst && tac->dst->global_symbol && tac->operation == IR_MOVE) {
            Value *dst = add_load_from_tac(function, tac, tac->dst);
            Type *type = tac->dst->type;
            tac->dst = dup_value(dst);
            tac->dst->is_lvalue = 1;
            tac->dst->type = type;
        }
        if (tac->src1 && tac->src1->global_symbol && tac->operation == IR_MOVE) {
            Value *dst = add_load_from_tac(function, tac, tac->src1);
            tac->src1 = dst;
            if (!is_pointer_to_function_type(tac->src1->type))
                tac->operation = IR_INDIRECT;
        }
        else if (tac->src1 && tac->src1->global_symbol && tac->operation == IR_ADDRESS_OF) {
            tac->operation = IR_ADDRESS_OF_FROM_GOT;
            if (tac->src1->offset) {
                int offset = tac->src1->offset;
                tac->src1->offset = 0;
                Value *dst_with_offset = dup_value(tac->dst);
                tac->dst = dup_value(tac->dst);
                tac->dst->vreg = ++function->vreg_count;
                tac = insert_instruction_after_from_operation(tac, IR_ADD, dst_with_offset, tac->dst, new_integral_constant(TYPE_INT, offset));
            }
        }
    }
}
void add_PIC_load_and_saves ( Function * function ) { if ( ! opt_PIC ) return ; for ( Tac * tac = function -> ir ; tac ; tac = tac -> next ) { if ( tac -> dst && tac -> dst -> global_symbol && tac -> operation != IR_MOVE ) panic ( " " ) ; if ( tac -> src1 && tac -> src1 -> global_symbol && tac -> operation != IR_MOVE && tac -> operation != IR_CALL && tac -> operation != IR_ADDRESS_OF && tac -> operation != IR_DECL_LOCAL_COMP_OBJ ) panic ( " " , tac -> operation ) ; if ( tac -> src2 && tac -> src2 -> global_symbol ) panic ( " " , tac -> operation ) ; if ( tac -> dst && tac -> dst -> global_symbol && tac -> operation == IR_MOVE ) { Value * dst = add_load_from_tac ( function , tac , tac -> dst ) ; Type * type = tac -> dst -> type ; tac -> dst = dup_value ( dst ) ; tac -> dst -> is_lvalue = 1 ; tac -> dst -> type = type ; } if ( tac -> src1 && tac -> src1 -> global_symbol && tac -> operation == IR_MOVE ) { Value * dst = add_load_from_tac ( function , tac , tac -> src1 ) ; tac -> src1 = dst ; if ( ! is_pointer_to_function_type ( tac -> src1 -> type ) ) tac -> operation = IR_INDIRECT ; } else if ( tac -> src1 && tac -> src1 -> global_symbol && tac -> operation == IR_ADDRESS_OF ) { tac -> operation = IR_ADDRESS_OF_FROM_GOT ; if ( tac -> src1 -> offset ) { int offset = tac -> src1 -> offset ; tac -> src1 -> offset = 0 ; Value * dst_with_offset = dup_value ( tac -> dst ) ; tac -> dst = dup_value ( tac -> dst ) ; tac -> dst -> vreg = ++ function -> vreg_count ; tac = insert_instruction_after_from_operation ( tac , IR_ADD , dst_with_offset , tac -> dst , new_integral_constant ( TYPE_INT , offset ) ) ; } } } }
When compiled with Position Independent Code (PIC) , all accesses to global objects
go through a Global Offset Table (GOT).
When compiled with Position Independent Code ( PIC ) all accesses to global objects go through a Global Offset Table ( GOT ) .
// Ensure all global values are only ever loaded or saved // Convert a save of a global to a mov from the GOT followed by a store to a pointer in a register // Convert to a move to an lvalue in a register // Convert a load of a global to a mov from the GOT followed by an indirect // Convert to an indirect unless it's a pointer to a function