move lots of source files around to match their actual placement in the original tree

This commit is contained in:
Ash Wolf
2023-01-26 11:30:47 +00:00
parent fc0c4c0df7
commit 094b96ca1d
120 changed files with 400 additions and 392 deletions

View File

@@ -0,0 +1,393 @@
#include "compiler/FuncLevelAsmPPC.h"
#include "compiler/CCompiler.h"
#include "compiler/CError.h"
#include "compiler/CFunc.h"
#include "compiler/CMangler.h"
#include "compiler/CParser.h"
#include "compiler/CPrepTokenizer.h"
#include "compiler/CodeGen.h"
#include "compiler/Coloring.h"
#include "compiler/CompilerTools.h"
#include "compiler/DumpIR.h"
#include "compiler/InlineAsmPPC.h"
#include "compiler/InlineAsmRegisters.h"
#include "compiler/ObjGenMachO.h"
#include "compiler/PCode.h"
#include "compiler/PCodeAssembly.h"
#include "compiler/PCodeListing.h"
#include "compiler/PCodeUtilities.h"
#include "compiler/PPCError.h"
#include "compiler/RegisterInfo.h"
#include "compiler/StackFrame.h"
#include "compiler/TOC.h"
#include "compiler/objects.h"
static EntryPoint *entrypoints_head;
static EntryPoint **entrypoints_tail;
void setup_assembly_argument(Object *obj, short reg) {
VarInfo *vi;
Type *type;
vi = Registers_GetVarInfo(obj);
type = obj->type;
vi->used = 1;
if (!requires_frame) {
if (is_register_object(obj)) {
if (!reg)
CError_Error(CErrorStr263, obj->name->name);
if (TYPE_IS_8BYTES(type)) {
short regLo;
short regHi;
if (reg < 10) {
if (copts.littleendian) {
regLo = reg;
regHi = reg + 1;
} else {
regLo = reg + 1;
regHi = reg;
}
retain_GPR_pair(obj, regLo, regHi);
InlineAsm_InsertRegister(obj->name->name, RegClass_GPR, regLo, obj);
}
} else if (IS_TYPE_FLOAT(type)) {
retain_register(obj, RegClass_FPR, reg);
InlineAsm_InsertRegister(obj->name->name, RegClass_FPR, reg, obj);
} else if (IS_TYPE_VECTOR(type)) {
retain_register(obj, RegClass_VR, reg);
InlineAsm_InsertRegister(obj->name->name, RegClass_VR, reg, obj);
} else {
retain_register(obj, RegClass_GPR, reg);
InlineAsm_InsertRegister(obj->name->name, RegClass_GPR, reg, obj);
}
}
} else {
if (is_register_object(obj)) {
vi = Registers_GetVarInfo(obj);
if (!vi->reg) {
assign_register_by_type(obj);
if (!(vi->flags & VarInfoFlag2))
CError_Error(CErrorStr263, obj->name->name);
else
InlineAsm_InsertRegister(obj->name->name, vi->rclass, vi->reg, obj);
}
}
}
}
void assign_local_addresses(void) {
VarInfo *vi;
ObjectList *list;
Object *object;
for (list = locals; list; list = list->next) {
vi = CodeGen_GetNewVarInfo();
list->object->u.var.info = vi;
list->object->flags |= OBJECT_USED;
vi->used = 1;
}
for (list = locals; list; list = list->next) {
object = list->object;
if (is_register_object(object)) {
vi = Registers_GetVarInfo(object);
if (!vi->reg) {
assign_register_by_type(object);
if (!(vi->flags & VarInfoFlag2))
CError_Error(CErrorStr263, object->name->name);
else
InlineAsm_InsertRegister(object->name->name, vi->rclass, vi->reg, object);
}
}
}
for (list = locals; list; list = list->next) {
object = list->object;
if (OBJECT_REG(object) == 0)
assign_local_memory(object);
}
}
static void FuncAsm_PreScanDirectives(void) {
SInt32 directive;
Boolean save_eoltokens;
in_assembler = 1;
save_eoltokens = cprep_eoltokens;
cprep_eoltokens = 1;
if (setjmp(InlineAsm_assemblererror) == 0) {
while (tk == TK_IDENTIFIER && (directive = InlineAsm_IsDirective(AssemblerType_1))) {
InlineAsm_ProcessDirective(directive);
if (tk == ';' || tk == TK_EOL) {
CPrep_TokenStreamFlush();
tk = lex();
} else {
InlineAsm_SyntaxError(CErrorStr113);
}
if (directive == IADirective_FrAlloc) {
requires_frame = 1;
break;
} else if (directive == IADirective_NoFrAlloc) {
user_responsible_for_frame = 1;
break;
}
}
}
in_assembler = 0;
cprep_eoltokens = save_eoltokens;
}
static void FuncAsm_AddEntryPoint(Statement *stmt, PCodeBlock *block) {
EntryPoint *ep;
IAEntryPoint *ia_ep;
ia_ep = (IAEntryPoint *) stmt->expr;
ep = lalloc(sizeof(EntryPoint));
memclrw(ep, sizeof(EntryPoint));
ep->object = ia_ep->x8;
ep->block = block;
*entrypoints_tail = ep;
entrypoints_tail = &ep->next;
block->flags |= fPCBlockFlag8000;
}
void Assembler(Object *func) {
PCodeBlock *block;
Statement *stmt;
Boolean flag17;
Boolean flag16;
char *name;
InlineAsm *ia;
Boolean save_unusedvar;
Boolean save_unusedarg;
flag17 = 0;
flag16 = 0;
init_endian();
init_stack_globals(func);
memclrw(asm_alloc_flags, sizeof(asm_alloc_flags));
fralloc_parameter_area_size = 0;
user_responsible_for_frame = 0;
assembledinstructions = 0;
entrypoints_head = NULL;
entrypoints_tail = &entrypoints_head;
stmt = curstmt;
if (func && func->name)
PrintProgressFunction(func->name->name);
CodeGen_InitialSanityCheck();
if (func->qual & Q_INLINE)
PPCError_Warning(PPCErrorStr173);
CheckCLabels();
if (fatalerrors)
return;
if (copts.filesyminfo)
CPrep_SetSourceFile(&cparser_fileoffset);
sm_section = SECT_TEXT;
initpcode();
pclabel(prologue = makepcblock(), makepclabel());
pclabel(block = makepcblock(), makepclabel());
pcbranch(prologue, block->labels);
resetTOCvarinfo();
InlineAsm_InitializePPC();
FuncAsm_PreScanDirectives();
disable_optimizer = 1;
init_registers();
assign_arguments_to_memory(func, 0, 0);
init_frame_sizes(0);
if (copts.debuglisting)
DumpIR(stmt, func);
cprep_eoltokens = 1;
in_assembler = 1;
save_unusedvar = copts.warn_unusedvar;
save_unusedarg = copts.warn_unusedarg;
copts.warn_unusedvar = 0;
copts.warn_unusedarg = 0;
InlineAsm_ScanFunction('}');
expandTOCreferences(&stmt->next);
if (!anyerrors && copts.debuglisting)
DumpIR(stmt, func);
in_assembler = 0;
cprep_eoltokens = 0;
name = CMangler_GetLinkName(func)->name;
func->flags |= OBJECT_DEFINED;
if (fralloc_parameter_area_size)
update_out_param_size(fralloc_parameter_area_size);
if (!user_responsible_for_frame)
process_arguments(move_assigned_argument, 0);
branch_label(makepclabel());
assign_labels(stmt->next);
copts.warn_unusedvar = save_unusedvar;
copts.warn_unusedarg = save_unusedarg;
for (stmt = stmt->next; stmt; stmt = stmt->next) {
current_statement = stmt;
switch (stmt->type) {
case ST_ASM:
if ((ia = (InlineAsm *) stmt->expr)) {
if (ia->flags & IAFlag1) {
if (ia->opcode == IADirective_Entry) {
branch_label(makepclabel());
FuncAsm_AddEntryPoint(stmt, pclastblock);
} else if (ia->opcode == IADirective_FrFree) {
if (flag16)
PPCError_Error(PPCErrorStr188);
else
flag16 = 1;
asm_alloc_flags[3] = 1;
asm_alloc_flags[4] = 1;
branch_label(makepclabel());
epilogue = pclastblock;
pclastblock->flags |= fIsEpilogue;
CheckCLabels();
if (fatalerrors)
return;
pccomputepredecessors();
if (copts.debuglisting)
pclistblocks(name, "[FUNCTION-LEVEL ASM] INITIAL CODE");
colorinstructions(func);
if (copts.debuglisting)
pclistblocks(name, "[FUNCTION-LEVEL ASM] AFTER REGISTER COLORING");
compute_frame_sizes();
generate_prologue(prologue, 0);
epilogue = pclastblock;
generate_epilogue(epilogue, 0);
if (copts.debuglisting)
pclistblocks(name, "[FUNCTION-LEVEL ASM] AFTER PROLOGUE/EPILOGUE CREATION");
flag17 = 1;
}
} else {
branch_label(makepclabel());
asm_alloc_flags[6] = 0;
asm_alloc_flags[7] = 0;
InlineAsm_TranslateIRtoPCode(stmt);
asm_alloc_flags[4] = 0;
}
}
break;
case ST_LABEL:
if (!stmt->label->pclabel->resolved)
branch_label(stmt->label->pclabel);
break;
default:
CError_FATAL(525);
}
}
current_statement = NULL;
if (fatalerrors)
return;
CheckCLabels();
if (fatalerrors)
return;
if (!flag17) {
branch_label(makepclabel());
epilogue = pclastblock;
pclastblock->flags |= fIsEpilogue;
pccomputepredecessors();
if (copts.debuglisting)
pclistblocks(name, "[FUNCTION-LEVEL ASM] INITIAL CODE");
if (!asm_alloc_flags[1]) {
colorinstructions(func);
if (fatalerrors)
return;
if (copts.debuglisting)
pclistblocks(name, "[FUNCTION-LEVEL ASM] AFTER REGISTER COLORING");
}
compute_frame_sizes();
if (asm_alloc_flags[1])
no_frame_for_asm();
if (fatalerrors)
return;
if (!asm_alloc_flags[1]) {
generate_prologue(prologue, 0);
generate_epilogue(epilogue, !asm_alloc_flags[6] && !asm_alloc_flags[7]);
}
if (copts.debuglisting)
pclistblocks(name, "[FUNCTION-LEVEL ASM] AFTER PROLOGUE/EPILOGUE CREATION");
}
if (fatalerrors)
return;
if (!asm_alloc_flags[1] && needs_frame()) {
if (asm_alloc_flags[3]) {
if (!asm_alloc_flags[5] || !asm_alloc_flags[6])
PPCError_Warning(PPCErrorStr187, "blr");
if (asm_alloc_flags[8])
PPCError_Warning(PPCErrorStr186);
} else {
PPCError_Warning(PPCErrorStr185, "blr");
}
}
func->section = sm_section;
if (copts.filesyminfo)
symdeclend = CPrep_GetFileOffsetInfo(&cparser_fileoffset);
copts.peephole = 0;
if (pic_base_label)
pic_base_pcodelabel = pic_base_label->pclabel;
assemblefunction(func, entrypoints_head);
if (copts.debuglisting)
pclistblocks(CMangler_GetLinkName(func)->name, "[FUNCTION-LEVEL ASM] FINAL CODE");
CFunc_WarnUnused();
}
void SetupAssembler(void) {
}
void CleanupAssembler(void) {
}

View File

@@ -0,0 +1,230 @@
#include "compiler/GCCInlineAsm.h"
#include "compiler/CError.h"
#include "compiler/CExpr.h"
#include "compiler/CFunc.h"
#include "compiler/CInt64.h"
#include "compiler/CParser.h"
#include "compiler/CPrep.h"
#include "compiler/CPrepTokenizer.h"
#include "compiler/InlineAsm.h"
#include "compiler/objects.h"
Statement *first_ST_ASM;
IALookupResult gcc_name_list[20];
int gcc_name_list_index;
void InlineAsm_SkipComment(void) {
while (1) {
if (tk != '/')
break;
if (lookahead() != '*')
break;
tk = lex();
while (!((tk = lex()) == '*' && (tk = lex()) == '/')) {
// nothing
}
tk = lex();
}
}
static char gcc_parse_attribute(void) {
char ch;
while (tk == TK_EOL)
tk = lex();
if (tk != '"')
CError_Error(CErrorStr105);
while ((tk = lex()) != TK_IDENTIFIER) {
// nothing
}
ch = tkidentifier->name[0];
if ((tk = lex()) != '"')
CError_Error(CErrorStr105);
tk = lex();
return ch;
}
static void gcc_parse_name(Boolean flag, char attribute) {
IALookupResult *nameentry;
ENode *expr;
Object *tempobj;
ENode *tempexpr;
Statement *stmt;
while (tk == TK_EOL)
tk = lex();
if (tk != '(')
CError_Error(CErrorStr114);
tk = lex();
if (flag) {
if (tk != TK_IDENTIFIER)
CError_Error(CErrorStr105);
InlineAsm_LookupSymbol(tkidentifier, &gcc_name_list[++gcc_name_list_index]);
if (gcc_name_list[gcc_name_list_index].object && gcc_name_list[gcc_name_list_index].object->u.var.info)
gcc_name_list[gcc_name_list_index].object->u.var.info->used = 1;
tk = lex();
} else {
in_assembler = 0;
cprep_nostring = 0;
nameentry = &gcc_name_list[++gcc_name_list_index];
expr = expression();
if (attribute == 'i' || attribute == 'I') {
if (!ENODE_IS(expr, EINTCONST))
CError_Error(CErrorStr144);
nameentry->value = CInt64_GetULong(&expr->data.intval);
nameentry->has_value = 1;
} else {
tempobj = create_temp_object(expr->rtype);
tempexpr = create_objectnode(tempobj);
if (tempobj->u.var.info)
tempobj->u.var.info->used = 1;
expr = makediadicnode(tempexpr, expr, EASS);
stmt = CFunc_InsertBeforeStatement(ST_EXPRESSION, first_ST_ASM);
first_ST_ASM = stmt->next;
if (!first_ST_ASM->next)
curstmt = first_ST_ASM;
stmt->expr = expr;
nameentry->name = tempobj->name;
nameentry->object = tempobj;
nameentry->label = NULL;
nameentry->type = NULL;
nameentry->has_value = 0;
}
}
cprep_nostring = 1;
in_assembler = 1;
if (tk != ')')
CError_Error(CErrorStr115);
tk = lex();
}
static void gcc_parse_expression(Boolean flag) {
while (1) {
gcc_parse_name(flag, gcc_parse_attribute());
if (tk != ',')
break;
tk = lex();
}
}
static void gcc_parse_input(void) {
if (tk == ':') {
if ((tk = lex()) == ':' || tk == ')' || tk == '}')
return;
gcc_parse_expression(0);
}
}
static void gcc_parse_output(void) {
if (tk == ':') {
if ((tk = lex()) == ':' || tk == ')' || tk == '}')
return;
gcc_parse_expression(1);
}
}
static void gcc_parse_killed(void) {
if (tk == ':') {
while (1) {
if ((tk = lex()) != '"')
return;
tk = lex();
while (1) {
if (tk == '"') {
if (lookahead() == ',') {
tk = lex();
break;
}
tk = lex();
return;
}
tk = lex();
}
}
}
}
static void gcc_replace_arg_st_asm(Statement *stmt) {
InlineAsm *ia;
int i;
IAOperand *op;
short effect;
short rclass;
SInt32 num;
if ((ia = (InlineAsm *) stmt->expr)) {
for (i = 0, op = ia->args; i < ia->argcount; i++, op++) {
switch (op->type) {
case IAOpnd_Imm:
case IAOpnd_Reg:
case IAOpnd_3:
case IAOpnd_4:
case IAOpnd_Lab:
break;
case IAOpnd_6:
if (op->u.unk6.unk4 == 2) {
effect = op->u.unk6.effect;
rclass = op->u.unk6.rclass;
num = op->u.unk6.num;
op->type = IAOpnd_Reg;
op->u.reg.effect = effect;
op->u.reg.rclass = rclass;
op->u.reg.object = NULL;
if (num <= gcc_name_list_index)
op->u.reg.object = gcc_name_list[num].object;
else
CError_Error(CErrorStr144);
op->u.reg.num = 0;
} else {
CError_FATAL(365);
}
break;
case IAOpnd_7:
op->type = IAOpnd_Imm;
op->u.imm.value = gcc_name_list[op->u.unk7.value].value;
break;
}
}
}
}
static void gcc_replace_arg(void) {
Statement *stmt;
for (stmt = first_ST_ASM; stmt; stmt = stmt->next) {
if (stmt->type == ST_ASM)
gcc_replace_arg_st_asm(stmt);
}
}
void InlineAsm_gcc_parse(void) {
gcc_name_list_index = -1;
cprep_eoltokens = 0;
if (tk == TK_EOL)
tk = lex();
gcc_parse_output();
gcc_parse_input();
gcc_parse_killed();
gcc_replace_arg();
}

View File

@@ -0,0 +1,680 @@
#include "compiler/InlineAsm.h"
#include "compiler/InlineAsmPPC.h"
#include "compiler/GCCInlineAsm.h"
#include "compiler/CompilerTools.h"
#include "compiler/CError.h"
#include "compiler/CExpr.h"
#include "compiler/CFunc.h"
#include "compiler/CInit.h"
#include "compiler/CInline.h"
#include "compiler/CInt64.h"
#include "compiler/CMachine.h"
#include "compiler/COptimizer.h"
#include "compiler/CParser.h"
#include "compiler/CPrep.h"
#include "compiler/CPrepTokenizer.h"
#include "compiler/CScope.h"
#include "compiler/PCode.h"
#include "compiler/Registers.h"
#include "compiler/objects.h"
#include "compiler/scopes.h"
#include "compiler/types.h"
int allow_array_expressions = 1;
int backtracking;
jmp_buf backtrack;
jmp_buf InlineAsm_assemblererror;
static int ASMstmtnb;
void AssemblerError(void) {
longjmp(InlineAsm_assemblererror, 1);
}
void InlineAsm_SyntaxError(short code) {
if (backtracking)
longjmp(backtrack, 1);
if (tk == TK_EOL || tk == ';')
code = CErrorStr112;
CError_Error(code);
}
CLabel *InlineAsm_LookupLabel(HashNameNode *name) {
CLabel *label;
for (label = Labels; label; label = label->next) {
if (name == label->name)
break;
}
return label;
}
CLabel *InlineAsm_DeclareLabel(HashNameNode *name) {
CLabel *label = newlabel();
label->name = name;
label->next = Labels;
Labels = label;
return label;
}
static void InlineAsm_DefineLabel(HashNameNode *name) {
CLabel *label;
Statement *stmt;
label = InlineAsm_LookupLabel(name);
if (!label) {
label = InlineAsm_DeclareLabel(name);
} else {
if (label->stmt)
CError_Error(CErrorStr171, name->name);
}
stmt = CFunc_AppendStatement(ST_LABEL);
stmt->label = label;
label->stmt = stmt;
}
Boolean InlineAsm_LookupSymbolOrTag(HashNameNode *name, IALookupResult *result, Boolean allow_tag) {
ObjBase *obj;
NameSpace *nspace;
NameSpaceObjectList *list;
result->name = name;
result->object = NULL;
result->label = NULL;
result->type = NULL;
result->has_value = 0;
if ((result->label = InlineAsm_LookupLabel(name)))
return 1;
for (nspace = cscope_current; nspace; nspace = nspace->parent) {
if ((list = CScope_FindName(nspace, name))) {
obj = list->object;
switch (obj->otype) {
case OT_ENUMCONST:
result->has_value = 1;
result->value = OBJ_ENUM_CONST(list->object)->val.lo;
return 1;
case OT_OBJECT:
if (OBJECT(obj)->datatype == DABSOLUTE) {
result->has_value = 1;
result->value = OBJECT(obj)->u.address;
} else {
if (OBJECT(obj)->datatype == DDATA && (OBJECT(obj)->qual & Q_INLINE_DATA))
CInit_ExportConst(OBJECT(obj));
result->object = OBJECT(obj);
}
return 1;
case OT_TYPE:
result->type = OBJ_TYPE(obj)->type;
return 1;
case OT_TYPETAG:
if (allow_tag) {
result->type = OBJ_TYPE_TAG(obj)->type;
return 1;
}
case OT_NAMESPACE:
case OT_MEMBERVAR:
return 0;
default:
CError_FATAL(245);
}
}
}
return 0;
}
Boolean InlineAsm_LookupSymbol(HashNameNode *name, IALookupResult *result) {
return InlineAsm_LookupSymbolOrTag(name, result, 0);
}
static ObjMemberVar *isclassmember(TypeClass *tclass, HashNameNode *name) {
NameSpaceObjectList *list;
list = CScope_FindName(tclass->nspace, name);
return (list && list->object->otype == OT_MEMBERVAR) ? OBJ_MEMBER_VAR(list->object) : NULL;
}
SInt32 InlineAsm_StructMemberOffset(Type *type) {
StructMember *member;
ObjMemberVar *ivar;
SInt32 offset = 0;
do {
if (IS_TYPE_STRUCT(type)) {
tk = lex();
if (tk != TK_IDENTIFIER)
InlineAsm_SyntaxError(CErrorStr107);
member = ismember(TYPE_STRUCT(type), tkidentifier);
if (!member)
CError_Error(CErrorStr150, tkidentifier->name);
offset += member->offset;
type = member->type;
tk = lex();
} else if (IS_TYPE_CLASS(type)) {
tk = lex();
if (tk != TK_IDENTIFIER)
InlineAsm_SyntaxError(CErrorStr107);
ivar = isclassmember(TYPE_CLASS(type), tkidentifier);
if (!ivar)
CError_Error(CErrorStr150, tkidentifier->name);
offset += ivar->offset;
type = ivar->type;
tk = lex();
} else {
CError_Error(CErrorStr149);
}
} while (tk == '.');
return offset;
}
SInt32 InlineAsm_StructArrayMemberOffset(Type *type) {
StructMember *member;
ObjMemberVar *ivar;
SInt32 offset = 0;
do {
if (tk == '.') {
if (IS_TYPE_STRUCT(type)) {
tk = lex();
if (tk != TK_IDENTIFIER)
InlineAsm_SyntaxError(CErrorStr107);
member = ismember(TYPE_STRUCT(type), tkidentifier);
if (!member)
CError_Error(CErrorStr150, tkidentifier->name);
offset += member->offset;
type = member->type;
tk = lex();
} else if (IS_TYPE_CLASS(type)) {
tk = lex();
if (tk != TK_IDENTIFIER)
InlineAsm_SyntaxError(CErrorStr107);
ivar = isclassmember(TYPE_CLASS(type), tkidentifier);
if (!ivar)
CError_Error(CErrorStr150, tkidentifier->name);
offset += ivar->offset;
type = ivar->type;
tk = lex();
} else {
CError_Error(CErrorStr149);
}
} else {
if (IS_TYPE_ARRAY(type)) {
type = TPTR_TARGET(type);
tk = lex();
offset += type->size * InlineAsm_ConstantExpression();
if (tk != ']')
InlineAsm_SyntaxError(125);
tk = lex();
} else {
CError_Error(CErrorStr148);
}
}
} while (tk == '.' || tk == '[');
return offset;
}
SInt32 InlineAsm_StructPointerMemberOffset(Type *type) {
StructMember *member;
ObjMemberVar *ivar;
SInt32 offset;
tk = lex();
if (tk != TK_IDENTIFIER)
InlineAsm_SyntaxError(107);
if (IS_TYPE_STRUCT(type)) {
member = ismember(TYPE_STRUCT(type), tkidentifier);
if (!member)
CError_Error(CErrorStr150, tkidentifier->name);
offset = member->offset;
type = member->type;
} else {
ivar = isclassmember(TYPE_CLASS(type), tkidentifier);
if (!ivar)
CError_Error(CErrorStr150, tkidentifier->name);
offset = ivar->offset;
type = ivar->type;
}
tk = lex();
if (tk == '.' || tk == '[')
offset += InlineAsm_StructArrayMemberOffset(type);
return offset;
}
static SInt32 DiadicOperator(SInt32 left, short op, SInt32 right) {
CInt64 left64;
CInt64 right64;
CInt64_SetLong(&left64, left);
CInt64_SetLong(&right64, right);
right64 = CMach_CalcIntDiadic(TYPE(&stsignedint), left64, op, right64);
return CInt64_GetULong(&right64);
}
static SInt32 PrimaryExpression(void) {
IALookupResult result;
SInt32 value;
switch (tk) {
case TK_IDENTIFIER:
if (InlineAsm_LookupSymbol(tkidentifier, &result)) {
if (result.has_value) {
tk = lex();
return result.value;
}
if (result.type && (IS_TYPE_STRUCT(result.type) || IS_TYPE_CLASS(result.type))) {
tk = lex();
if (tk != '.')
InlineAsm_SyntaxError(120);
if (allow_array_expressions)
return InlineAsm_StructArrayMemberOffset(result.type);
else
return InlineAsm_StructMemberOffset(result.type);
} else {
InlineAsm_SyntaxError(124);
}
} else {
InlineAsm_SyntaxError(124);
}
break;
case TK_INTCONST:
value = tkintconst.lo;
tk = lex();
return value;
case TK_SIZEOF:
return scansizeof();
case '+':
tk = lex();
return PrimaryExpression();
case '-':
tk = lex();
return -PrimaryExpression();
case '!':
tk = lex();
return PrimaryExpression() == 0;
case '~':
tk = lex();
return ~PrimaryExpression();
case '(':
tk = lex();
value = InlineAsm_ConstantExpression();
if (tk != ')')
InlineAsm_SyntaxError(115);
tk = lex();
return value;
default:
InlineAsm_SyntaxError(120);
}
return 0;
}
static SInt32 ConstantExpressionTail(SInt32 value) {
SInt32 right;
short left_token;
short right_prec;
while (1) {
left_token = tk;
tk = lex();
right = PrimaryExpression();
right_prec = GetPrec(tk);
if (right_prec == 0)
return DiadicOperator(value, left_token, right);
if (GetPrec(left_token) >= right_prec) {
value = DiadicOperator(value, left_token, right);
} else {
value = DiadicOperator(value, left_token, ConstantExpressionTail(right));
if (GetPrec(tk) == 0)
return value;
}
}
}
SInt32 InlineAsm_ConstantExpression(void) {
SInt32 value = PrimaryExpression();
if (GetPrec(tk) == 0)
return value;
else
return ConstantExpressionTail(value);
}
HashNameNode *MakeLocalLabel(CInt64 num) {
char buf[80];
sprintf(buf, "@%i_%i", ASMstmtnb, CInt64_GetULong(&num));
return GetHashNameNodeExport(buf);
}
static void ScanOptionalLabel(void) {
if (tk == TK_INTCONST) {
if (lookahead() == ':') {
InlineAsm_DefineLabel(MakeLocalLabel(tkintconst));
tk = lex();
tk = lex();
}
} else {
if (tkidentifier->name[0] == '@') {
InlineAsm_DefineLabel(tkidentifier);
tk = lex();
if (tk == ':')
tk = lex();
} else {
HashNameNode *name = tkidentifier;
short t = lookahead();
tkidentifier = name;
if (t == ':') {
InlineAsm_DefineLabel(name);
tk = lex();
tk = lex();
}
}
}
}
static void ScanStatements(volatile short endToken, AssemblerType mode) {
if (setjmp(InlineAsm_assemblererror)) {
while (tk != TK_EOL && tk != endToken && tk != '}' && tk)
tk = lex();
if (tk == ';' || tk == TK_EOL)
tk = lex();
} else {
InlineAsm_Initialize(mode);
InlineAsm_gccmode = 0;
if (setjmp(InlineAsm_assemblererror)) {
while (tk != ';' && tk != TK_EOL && tk != endToken && tk != '}' && tk)
tk = lex();
if (tk == ';' || tk == TK_EOL)
tk = lex();
}
while (tk && tk != endToken) {
backtracking = 0;
sourceoffset = CPrep_GetFileOffsetInfo(&cparser_fileoffset);
if (tk == '"') {
if (InlineAsm_gccmode) {
tk = lex();
InlineAsm_gcc_parse();
} else {
InlineAsm_gccmode = 1;
copts.cplusplus = 0;
copts.asmpoundcomment = 1;
tk = lex();
}
}
if (tk == '.') {
InlineAsm_ScanAssemblyDirective();
} else if (tk == TK_IDENTIFIER) {
ScanOptionalLabel();
if (tk == TK_IDENTIFIER)
InlineAsm_ScanAssemblyInstruction();
} else if (tk == TK_INTCONST) {
ScanOptionalLabel();
if (tk == TK_IDENTIFIER)
InlineAsm_ScanAssemblyInstruction();
}
if (InlineAsm_gccmode && tk == '"') {
tk = lex();
InlineAsm_gcc_parse();
}
if (tk == ';' || tk == TK_EOL) {
CPrep_TokenStreamFlush();
tk = lex();
} else if (tk != endToken) {
if (endToken == ')')
CError_Error(CErrorStr115);
else
CError_Error(CErrorStr113);
}
}
}
}
void InlineAsm_ScanStatements(volatile short endToken) {
ScanStatements(endToken, AssemblerType_0);
}
void InlineAsm_ScanFunction(volatile short endToken) {
ScanStatements(endToken, AssemblerType_1);
}
void InlineAsm_Assemble(void) {
short token = (tk == '(') ? ')' : '}';
char save_pc = copts.asmpoundcomment;
char save_cpp = copts.cplusplus;
cprep_nostring = 1;
CFunc_AppendStatement(ST_NOP);
first_ST_ASM = curstmt;
ASMstmtnb++;
cprep_eoltokens = 1;
in_assembler = 1;
tk = lex();
InlineAsm_ScanStatements(token);
in_assembler = 0;
cprep_eoltokens = 0;
cprep_nostring = 0;
copts.asmpoundcomment = save_pc;
copts.cplusplus = save_cpp;
}
void InlineAsm_PackAsmStatement(Statement *stmt, Statement *first, void **output, SInt32 *outsize) {
InlineAsm *src;
InlineAsm *dest;
IAOperand *op;
SInt32 i;
SInt32 size;
src = (InlineAsm *) stmt->expr;
size = sizeof(InlineAsm) + sizeof(IAOperand) * src->argcount;
dest = galloc(size);
memcpy(dest, src, size);
for (i = 0, op = dest->args; i < dest->argcount; i++, op++) {
switch (op->type) {
case IAOpnd_0:
break;
case IAOpnd_Reg:
case IAOpnd_4:
op->u.reg.object = (Object *) CInline_GetLocalID(op->u.reg.object);
break;
case IAOpnd_Lab:
op->u.lab.label = (CLabel *) CInline_GetStatementNumber(first, op->u.lab.label->stmt);
break;
case IAOpnd_LabDiff:
op->u.labdiff.label1 = (CLabel *) CInline_GetStatementNumber(first, op->u.labdiff.label1->stmt);
op->u.labdiff.label2 = (CLabel *) CInline_GetStatementNumber(first, op->u.labdiff.label2->stmt);
break;
}
}
*output = dest;
*outsize = size;
}
void InlineAsm_UnpackAsmStatement(Statement *stmt, CLabel **labelArray, Boolean flag, void *data, SInt32 size) {
InlineAsm *ia;
IAOperand *op;
SInt32 i;
ia = galloc(size);
memcpy(ia, data, size);
for (i = 0, op = ia->args; i < ia->argcount; i++, op++) {
switch (op->type) {
case IAOpnd_0:
break;
case IAOpnd_Reg:
case IAOpnd_4:
op->u.reg.object = CInline_GetLocalObj((SInt32) op->u.reg.object, flag);
break;
case IAOpnd_Lab:
op->u.lab.label = labelArray[(SInt16) op->u.lab.label];
break;
case IAOpnd_LabDiff:
op->u.labdiff.label1 = labelArray[(SInt16) op->u.labdiff.label1];
op->u.labdiff.label2 = labelArray[(SInt16) op->u.labdiff.label2];
break;
}
}
stmt->expr = (ENode *) ia;
}
void InlineAsm_CheckLocalUsage(Statement *stmt) {
InlineAsm *ia = (InlineAsm *) stmt->expr;
IAOperand *op;
SInt32 i;
for (i = 0, op = ia->args; i < ia->argcount; i++, op++) {
switch (op->type) {
case IAOpnd_Reg:
if (op->u.reg.object)
SetVarUsage(op->u.reg.object, 0);
break;
case IAOpnd_4:
SetVarUsage(op->u.obj.obj, 1);
break;
}
}
}
CLabel *InlineAsm_GetReferencedLabel(Statement *stmt) {
InlineAsm *ia = (InlineAsm *) stmt->expr;
IAOperand *op;
SInt32 i;
for (i = 0, op = ia->args; i < ia->argcount; i++, op++) {
if (op->type == IAOpnd_Lab)
return op->u.lab.label;
if (op->type == IAOpnd_LabDiff)
return op->u.labdiff.label1;
}
return NULL;
}
CLabel *InlineAsm_GetReferencedLabel2(Statement *stmt) {
InlineAsm *ia = (InlineAsm *) stmt->expr;
IAOperand *op;
SInt32 i;
for (i = 0, op = ia->args; i < ia->argcount; i++, op++) {
if (op->type == IAOpnd_LabDiff)
return op->u.labdiff.label2;
}
return NULL;
}
Object *InlineAsm_GetObjectOffset(InlineAsm *ia, SInt32 index, SInt32 *offset) {
IAOperand *op;
SInt32 i;
SInt32 counter;
for (i = 0, counter = 0, op = ia->args; i < ia->argcount; i++, op++) {
if (op->type == IAOpnd_3) {
if (counter++ == index) {
*offset = ((intptr_t) &op->u.obj.obj) - ((intptr_t) ia);
return op->u.obj.obj;
}
}
}
return NULL;
}
char *InlineAsm_DumpStatement(Statement *stmt) {
static char buffer[1024];
InlineAsm *ia;
IAOperand *arg;
int i;
char ch;
SInt32 offset;
ia = (InlineAsm *) stmt->expr;
strcpy(buffer, "\"");
strcat(buffer, InlineAsm_GetMnemonic(ia));
strcat(buffer, "\"");
for (i = 0, arg = ia->args; i < ia->argcount; i++, arg++) {
char argbuf[1024];
switch (arg->type) {
case IAOpnd_Imm:
sprintf(argbuf, " imm(%ld)", arg->u.imm.value);
break;
case IAOpnd_Reg:
ch = ' ';
if (arg->u.reg.effect & EffectWrite) {
if (arg->u.reg.effect & EffectRead)
ch = '+';
else
ch = '=';
} else {
if (!(arg->u.reg.effect & EffectRead))
ch = '0';
}
if (arg->u.reg.object) {
sprintf(argbuf,
"%creg(%s)",
ch,
arg->u.reg.object->name->name);
} else {
sprintf(argbuf,
"%creg(%s%d)",
ch,
register_class_name[arg->u.reg.rclass],
arg->u.reg.num);
}
break;
case IAOpnd_3:
case IAOpnd_4:
if (arg->u.obj.offset > 0)
sprintf(argbuf, " obj(%s+%ld)", arg->u.obj.obj->name->name, arg->u.obj.offset);
else if (arg->u.obj.offset < 0)
sprintf(argbuf, " obj(%s-%ld)", arg->u.obj.obj->name->name, -arg->u.obj.offset);
else
sprintf(argbuf, " obj(%s)", arg->u.obj.obj->name->name);
break;
case IAOpnd_Lab:
sprintf(argbuf, " lab(%s)", arg->u.lab.label->uniquename->name);
break;
case IAOpnd_LabDiff:
offset = !arg->negated ? 0 : arg->u.labdiff.offset;
sprintf(argbuf,
" labdiff(%s-%s%c%d)",
arg->u.labdiff.label1->uniquename->name,
arg->u.labdiff.label2->uniquename->name,
(arg->negated == 1) ? '-' : '+',
offset
);
break;
}
strcat(buffer, argbuf);
}
return buffer;
}

File diff suppressed because it is too large Load Diff