ex λ C: Array layout and indexing CS 251 Fall 2019 CS 240 Spring 2020 Principles of Programming Languages Foundations of Computer Systems Ben Wood Ben Wood int val[5]; +0 +4 +8 +12 +16 Representing Write x86 code to load val[i] into %eax . 1. Assume: • Base address of val is in %rdi Data Structures i is in %rsi • movl (%rdi, %rsi, 4), %eax Multidimensional arrays C structs 2. Assume: • Base address of val is 28(%rsp) • i is in %rcx movl 28(%rsp, %rcx, 4), %eax https://cs.wellesley.edu/~cs240/s20/ Representing Data Structures 1 Representing Data Structures 2 reminder ex C: Arrays of pointers to arrays of … C: Translate to x86 void copyleft(int** zips, long i, long j) { C int** zips = (int**)malloc(sizeof(int*)*3); zips[i][j] = zips[i][j - 1]; ... } zips[0] = (int*)malloc(sizeof(int)*5); ... int* zip0 = zips[0]; zips NULL zip0[0] = 0; 0 2 4 8 2 zips[0][1] = 2; 0 2 4 8 1 zips[0][2] = 4; zips[0][3] = 8; zips[0][4] = 1; zips copyleft: # %rax ← zips[i] movq (%rdi,%rsi,8), %rax ??? ??? # %rcx ← %rax[j] movq (%rax,%rdx,4), %rcx movq %rcx, -4(%rax,%rdx,4) # %rax[j-1] ← %rcx retq 0 2 4 8 1 Java int[][] zips = new int[3][]; zips[0] = new int[5] {0, 2, 4, 8, 1}; Representing Data Structures 3 Representing Data Structures 4
ex C: Row-major C: Strange array indexing examples a[0][0] • • • a[0][C-1] nested arrays • • int sea[4][5]; • • • • 9 8 1 9 5 9 8 1 0 5 9 8 1 0 3 9 8 1 1 5 a[R-1][0] • • • a[R-1][C-1] int a[ R ][ C ]; 76 96 116 136 156 a a a a a a [0] • • • [0] [1] • • • [1] • • • [ R -1] • • • [ R -1] Reference Address Value [0] [ C -1] [0] [ C -1] [0] [ C -1] 76+20*3+4*3 = 148 1 sea[3][3] Suppose a 's base address is A . 76+20*2+4*5 = 136 9 sea[2][5] &a[i][j] is A + C × sizeof(int) × i + sizeof(int) × j 76+20*2+4*-1 = 112 5 sea[2][-1] 76+20*4+4*-1 = 152 5 (regular unscaled arithmetic) sea[4][-1] 76+20*0+4*19 = 152 5 sea[0][19] 76+20*0+4*-1 = 72 ?? sea[0][-1] int* b = (int*)a; // Treat as larger 1D array C does not do any bounds checking. &a[i][j] == &b[ C *i + j ] Row-major array layout is guaranteed. Representing Data Structures 5 Representing Data Structures 6 C structs C: Accessing struct field Base address struct rec { int i; i a p int a[3]; Like Java class/object Offset: without methods. struct rec { int* p; +0 +4 +16 +24 r r+4+4*index int i; Memory Layout }; Compiler determines: int a[3]; • Total size int* p; i a p struct rec x; • Offset of each field }; struct rec y; 0 4 16 24 x.i = 1; int get_i_plus_elem(struct rec* r, int index) { x x.a[1] = 2; return r->i + r->a[index]; x.p = &(x.i); } // copy full struct movl 0(%rdi),%eax # Mem[r+0] y y = x; addl 4(%rdi,%rsi,4),%eax # Mem[r+4*index+4] retq struct rec* z; z = &y; (*z).i++; z // same as: z->i++ Representing Data Structures 7 Representing Data Structures 8
C: Struct field alignment C: Struct packing Put large data types first: Unaligned Data struct S1 { struct S2 { struct S1 { char c; c v i double v; double v; char c; p p+1 p+9 p+13 int i; double v; int i; char c; }* p; int i; programmer Aligned Data } * q; } * p; Defines new struct type and declares variable p Primitive data type requires K bytes of type struct S1* Address must be multiple of K C: align every struct field accordingly. c 7 bytes v i p+0 p+8 p+16 p+20 7 bytes c v i p+0 p+8 p+16 p+20 c X internal fragmentation v i Multiple of 8 Multiple of 4 q+0 q+8 q+12 q+13 but actually… Representing Data Structures 9 Representing Data Structures 10 C: Struct alignment (full) Array in struct Base and total size must align largest internal primitive type. struct rec { Fields must align their type's largest alignment requirement. int i; i a p int a[3]; int* p; Oftset: 0 4 16 24 struct S1 { }; char c; double v; int i; } * p; Struct in array 7 bytes c v i a+0 a+16 a+32 a+48 struct S2 { • • • p+0 p+8 p+16 p+20 a[0] a[1] a[2] double v; internal fragmentation int i; external fragmentation struct S2 { char c; double v; } a[10] ; v i c 3 bytes int i; v i c 3 bytes char c; a+16 a+24 a+28 a+32 q+12 q+0 q+8 q+16 } * q; Representing Data Structures 11 Representing Data Structures 12
ex C: typedef Linked Lists head next typedef // give type T another name: U struct Node { value 2 struct Node* next; next typedef T U; int value; value 4 } Node; next NULL // struct types can be verbose Implement append in x86: value 6 struct Node { ... }; void append(Node* head, int x) { ... // assume head != NULL struct Node* n = …; Node* cursor = head; // find tail while (cursor->next != NULL) { // typedef can help cursor = cursor->next; typedef struct Node { } ... Node* n = (Node*)malloc(sizeof(Node)); // error checking omitted } Node; // for x86 simplicity ... cursor->next = n; Node* n = ...; n->next = NULL; n->value = x; } Try a recursive version too. Representing Data Structures 13 Representing Data Structures 14 append: ex Linked Lists head pushq %rbp movl %esi, %ebp next typedef pushq %rbx struct Node { value 2 movq %rdi, %rbx struct Node* next; next subq $8, %rsp int value; jmp .L3 value 4 } Node; .L6: next NULL movq %rax, %rbx Implement append in x86: value 6 .L3: movq (%rbx), %rax void append(Node* head, int x) { testq %rax, %rax // assume head != NULL jne .L6 Node* cursor = head; movl $16, %edi // find tail call malloc while (cursor->next != NULL) { movq %rax, (%rbx) cursor = cursor->next; movq $0, (%rax) } movl %ebp, 8(%rax) Node* n = (Node*)malloc(sizeof(Node)); addq $8, %rsp // error checking omitted popq %rbx // for x86 simplicity popq %rbp cursor->next = n; ret n->next = NULL; n->value = x; } Try a recursive version too. Representing Data Structures 15
Recommend
More recommend