Xcode のファイル(Xobject) フォーマット


履歴:
Xcode は、C言語プログラムに復元可能な中間コードである。このコードレベ ルでは、以下の特徴を持つ:

記法:

以下の記述では、BNFを用いる。

Xcode の テキスト表現

Xcode のexpressionは、tree構造をもつデータ構造を表現するためのもので、 テキスト形式では、以下のように表現される:
Xcode_expr :=  
          '(' opcode Xcode_expr* ')'
	| Xcode_terminal_expr

Xcode_terminal_expr := 
	  '(' opcode number ')'			/* for number */
	| '(' opcode symbol ')'			/* symbol */
	| '(' opcode string ')'			/* string */
	| '(' opcode number number ')' 		/* double word */   

opcode := code_name [':' data_type ['@'[file_name.]line_number]]
code_name := symbol
file_name := symbol
line_number := number 

string := '"' ... '"'
それぞれの文が、どのように変換されるかについては、後述。

Xcode ファイル・トップレベル

ファイルは'%'でセパレートされた3つのセクションからなる:
xcode_file := 
	type_table
	'%'
	global_id_table
	'%'
	global_decl_list

type_table セクション

type_table セクションは、このファイル全体で使われているデータ型につい てのテーブルである。プログラム中で参照されるデータ型を表現する type_entryの並びである:
type_table := {type_entry}*
type_entry := 
	  pointer_type_entry 
	| function_type_entry
	| array_type_entry
	| structure_or_union_type_entry
	| enum_type_entry

type_id タイプ識別子

type_idは、タイプの識別子である。基本データ型の他に、ポインタなど派生 するタイプに関しては、先頭の1文字が種別を表し、英数字からなる識別子を 付ける。
type_id := 
	  P_type_id   	/* 'P'+数字* からなる文字列 */
	| F_type_id	/* 'F'+数字* からなる文字列 */
	| A_type_id 	/* 'A'+数字* からなる文字列 */
	| SU_type_id	/* 'S'or'U'+数字* からなる文字列 */
	| E_type_id 	/* 'E'+数字* からなる文字列 */
	| 'void'
	| 'char'
	| 'int'
	| 'long'
	| 'long_long'
	| 'unsigned_char'
	| 'unsigned_short'
	| 'unsigned'
	| 'unsigned_long'
	| 'unsigned_long_long'
	| 'float'
	| 'double'
	| 'long_double'

type_size := number

type_align := number

is_const := 0 | 1

is_volatile := 0 | 1

is_volatile := 0 | 1

type_entryの始めのtype_id type_size type_align is_const is_volatile は共通である。それぞれ、このタイプの識別子、サイズ、アライメント、 constか、volatileかを示す。

ポインタ型 type_entry

ポインタ型は、ref_type_idで、参照するタイプを示す。
pointer_type_entry :=
   '{' P_type_id type_size type_align is_const is_volatile
       ref_type_id '}'

ref_type_id := type_id
例:"int *"に対応するtype_entryは以下のようになる。
{ P0123 4 4 0 0 int}

関数型 type_entry

関数型は、ref_type_idで関数の返す値のデータ型を指定する。 param_listで、引数の (proto_typeはプロトタイプ宣言されているかどうか?)
function_type_entry := 
   '{' F_type_id type_size type_align is_const is_volatile 
       ret_type_id is_proto param_list '}'

ret_type_id :=  type_id

is_proto := 0 | 1

param_list := (LIST (IDNET param_name1) (INDENT param_name2) ...)
例: "double foo(int a,int b)" のfooに対するデータ型は以下のようになる。
{F023 0 0 0 0 double 0 (LIST (IDENT a) (IDENT b))}

配列型 type_entry

配列型は、配列の要素のデータ型elem_type_idと配列の次元をn_dimを指定する。 なお、type_sizeは配列全体のサイズをバイト数で指定する。
array_type_entry := 
   '{' A_type_id type_size type_align is_const is_volatile 
       elem_type_id n_dim '}'

elem_type_id := type_id

n_dim := number 
例: "int a[10]"のaに対するtype_entryは以下のようになる。
{A011 0x28 0x4 0 0 int 0xa}

構造体型 type_entry

struct/unionの構造体データ型は、メンバーに対するシンボルテーブル id_listを指定する。
struct_or_union_type_entry :=
   '{' SU_type_id type_size type_align is_const is_volatile 
       member_id_list '}'
例: "struct {int x1; int y1;} S;"のSに対するtype_entryは以下のように なる。
{S6e8e0 0x8 0x4 0 0  [x1 * int ()] [y1 * int ()] }

enum型 type_entry

enum型は、enumのメンバー識別子のリストを指定する。
enum_type_entry :=
   '{' E_type_id type_size type_align is_const is_volatile 
       moe_list '}'

moe_list := (LIST (IDNET moe_name1) (INDENT moe_name2) ...)

例: "enum { e1,e2,e3 } ee; "のeeに対するtype_entryは以下のようになる。
{E6b510 0x4 0x4 0 0 (LIST (IDENT e1) (IDENT e2) (IDENT e3))}

global_id_table セクション

global_id_table セクションは、このファイルスコープにおいて、大域的に定 義されているシンボルの並びである。
global_id_table := id_list

id_list シンボルテーブル

id_listとは、シンボルテーブルを構成するid_entryの並びである。 シンボルテーブルは以下の場所に用いられる:
id_list := { id_entry }*

id_entry := '[' id_symbol storage_class type_id value_expr ['*'] ']'

storage_class := 
	  '*'
	| 'auto'
	| 'param'
	| 'extern'
	| 'extern_def'
	| 'static'
	| 'register'
	| 'label'
	| 'tagname'
	| 'moe'
	| 'typedef_name'
例: "int xyz;"の変数xyzに対するシンボルテーブルエントリは以下のように なる。なお、P6e7e0は "int *"に対するtype_id。
 [xyz extern_def int (VAR_ADDR:P6e7e0 xyz)]
例: "int foo()"の関数fooに対するシンボルテーブルエントリは以下のよう になる。なお、F6f168は、fooのデータ型に対するtype_id。P6f1a8は、F6f168 へのポインタのtype_id。識別子fooは関数へのポインタになることに注意。
 [foo extern_def F6f168 (FUNC_ADDR:P6f1a8 foo)]

global_decl_list セクション

global_decl_listセクションは、プログラム中の宣言を集めたものである。 glboal_declのXcode expressionの並びになる。
global_decl_list := {global_decl}*

global_decl := 
	  (LIST global_decl ... )
	| (FUNCTION_DEFINITION  (IDENT func_name) 
		(ID_LIST [id_list]) (LIST [param_decl_list]) body)
	| (EXT_DECL (IDENT var_name) ())
	| (VAR_DECL (IDENT var_name) initializer)

param_decl_list := {(VAR_DECL (IDENT param_name) ())}*

body := statement

Xcode Statement

Cプログラムの制御文の構文要素に対応する表現である。
statement := 
      (EXPR_STATEMENT expr)
    | (LIST statement1 statement2 ...)
    | (COMPOUND_STATEMENT (ID_LIST [id_list]) (LIST [var_decls])
          (LIST statement1 statement2 ....))
    | (IF_STATEMENT cond_expr then_statement else_statement)
    | (WHILE_STATEMENT cond_expr body_statement)
    | (DO_STATEMENT body_statement cond_expr)
    | (FOR_STATEMENT init_expr cond_expr iter_expr body_statement)
    | (BREAK_STATEMENT)
    | (CONTINUE_STATEMENT)
    | (RETURN_STATEMENT return_expr)
    | (GOTO_STATEMENT (IDENT label_symbol))
    | (STATEMENT_LABEL (IDENT label_symbol))
    | (SWITCH_STATEMENT switch_expr body_statement)
    | (CASE_LABEL case_expr)
    | (DEFAULT_LABEL)
    | (OMP_PRAGMA (INT_CONSTANT omp_dir_id) 
    	   (LIST omp_clause1 omp_clause2 ...) body_statement)

Xcode Expression

Cの式の構文要素に対応する表現である。 それぞれのXcodeには、データ型が加えられており、式のデータ型情報を取り 出すことができる。
expression := 
	  primary_expr
	| (unary_opcode operand_expr)
	| (binary_opcode left_expr right_expr)
	| (assign_binary_opcode left_expr right_expr)
	| (binary_opcode left_expr right_expr)
	| (logical_unary_opcode operand_expr)
	| (logical_binary_opcode left_expr right_expr)
	| (ASSIGN_EXPR left_expr right_expr)
	| (COMMA_EXPR left_expr right_expr)
	| (CONDITIONAL_EXPR cond_expr (LIST then_expr else_expr))
	| (POST_INCR_EXPR operand_expr)
	| (POST_DECR_EXPR operand_expr)
	| (FUNCTION_CALL func_expr (LIST arg_expr1 arg_expr2 ...))
	| (CAST_EXPR operand_expr)

binary_opcode := 
	  PLUS_EXPR
	| MINUS_EXPR
	| MUL_EXPR
	| DIV_EXPR
	| MOD_EXPR
	| LSHIFT_EXPR
	| RSHIFT_EXPR
	| BIT_AND_EXPR
	| BIT_OR_EXPR
	| BIT_XOR_EXPR

asg_binary_opcode := 
	  ASG_PLUS_EXPR
	| ASG_MINUS_EXPR
	| ASG_MUL_EXPR
	| ASG_DIV_EXPR
	| ASG_MOD_EXPR
	| ASG_BIT_AND_EXPR
	| ASG_LSHIFT_EXPR
	| ASG_RSHIFT_EXPR
	| ASG_BIT_OR_EXPR
	| ASG_BIT_XOR_EXPR

unary_opcode :=
	  UNARY_MINUS_EXPR
	| BIT_NOT_EXPR

logical_binary_opcode :=
	  LOG_EQ_EXPR
	| LOG_NEQ_EXPR
	| LOG_GE_EXPR
	| LOG_GT_EXPR
	| LOG_LE_EXPR	
	| LOG_LT_EXPR
	| LOG_AND_EXPR
	| LOG_OR_EXPR

logical_unary_opcode :=
	  LOG_NOT_EXPR

Xcode primary expression

primary_expr :=
	  constant_expr
	| (POINTER_REF addr_expr)
	| var_ref_expr
	| member_ref_expr
	| array_ref_expr
定数は、以下のように表現する。
constant_expr := 
	  (INT_CONSTANT number)
	| (FLOAT_CONSTANT num1 num2)  
	| (LONGLONG_CONSTANT num1 num2)
	| (STRING_CONSTANT "...") 
	| (MOE_CONSTANT moe_name)
	| (FUNC_ADDR func_name)
変数への参照は、大域変数、パラメータ変数、局所変数、それぞれに対して、 異なるXcodeを用いる。変数のアドレスを参照するVAR_ADDR, PARAM_ADDR, LVAR_ADDRと、変数を参照するVAR,PARAM,LVARがある。
var_ref_expr :=
	  (VAR var_name)
	| (VAR_ADDR var_name)
	| (PRAAM var_name)
	| (PARAM_ADDR var_name)
	| (LVAR var_name)
	| (LVAR_ADDR var_name)


配列要素への参照は、配列変数のアドレスを用いてアドレス計算し、
POINTER_REFで要素にアクセスする。(検討事項)
array_ref_expr := 
	  (ARRAY_ADDR var_name)
	| (LARRAY_ADDR var_name)
構造体メンバへの参照は、参照アドレスを参照するMEMBER_ADDRとメンバを参 照するMEMBER_REF、メンバ配列のアドレスを参照するMEMBER_ARRAY_ADDRがあ る。
member_ref_expr :=
	  (MEMBER_REF addr_expr (IDENT member_name))
	| (MEMBER_ADDR addr_expr (IDENT member_name))
	| (MEMBER_ARRAY_ADDR addr_expr (IDENT member_name))
例1:
int a[10];
int xyz;
struct {    int x;   int y;} S;
foo() {
	int *p; 
	p =  &xyz;	/* 文1 */
	a[4] = S.y;	/* 文2 */
}
文1:
      (EXPR_STATEMENT
        (ASSIGN_EXPR:P6fc98
          (POINTER_REF:P6fc98
            (LVAR_ADDR:P70768 p))
          (VAR_ADDR:P70828 xyz)))
もしくは、
      (EXPR_STATEMENT
        (ASSIGN_EXPR:P6fc98
          (LVAR:P6fc98 p)
          (VAR_ADDR:P70828 xyz)))
文2:
      (EXPR_STATEMENT
        (ASSIGN_EXPR:int
          (POINTER_REF:int
            (PLUS_EXPR:P708e8
              (ARRAY_ADDR:P708e8 a)
              (INT_CONSTANT:int 4)))
          (POINTER_REF:int
            (MEMBER_ADDR:int
              (VAR_ADDR:P70988 S)
              (IDENT:int y)))))
もしくは: (検討事項)
      (EXPR_STATEMENT
        (ASSIGN_EXPR:int
          (ARRAY_REF:int
              (ARRAY_ADDR:P708e8 a)
              (INT_CONSTANT:int 4))
          (MEMBER_REF:int
              (VAR_ADDR:P70988 S)
              (IDENT:int y))))