Make labels work in asm blocks; allow labels as

parameters.  Rename ValueRefList to ParamList
in AsmParser, since its only use is for parameters.

llvm-svn: 43734
This commit is contained in:
Dale Johannesen 2007-11-05 21:20:28 +00:00
parent 58473ab478
commit 4646aa3e33
11 changed files with 921 additions and 793 deletions

View File

@ -241,12 +241,12 @@ struct ArgListEntry {
typedef std::vector<struct ArgListEntry> ArgListType;
struct ValueRefListEntry {
struct ParamListEntry {
Value *Val;
uint16_t Attrs;
};
typedef std::vector<ValueRefListEntry> ValueRefList;
typedef std::vector<ParamListEntry> ParamList;
} // End llvm namespace

File diff suppressed because it is too large Load Diff

View File

@ -14,7 +14,7 @@ typedef union {
llvm::ArgListType *ArgList;
llvm::TypeWithAttrs TypeWithAttrs;
llvm::TypeWithAttrsList *TypeWithAttrsList;
llvm::ValueRefList *ValueRefList;
llvm::ParamList *ParamList;
// Represent the RHS of PHI node
std::list<std::pair<llvm::Value*,

View File

@ -981,7 +981,7 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
llvm::ArgListType *ArgList;
llvm::TypeWithAttrs TypeWithAttrs;
llvm::TypeWithAttrsList *TypeWithAttrsList;
llvm::ValueRefList *ValueRefList;
llvm::ParamList *ParamList;
// Represent the RHS of PHI node
std::list<std::pair<llvm::Value*,
@ -1021,7 +1021,7 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
%type <ConstVector> ConstVector
%type <ArgList> ArgList ArgListH
%type <PHIList> PHIList
%type <ValueRefList> ValueRefList // For call param lists & GEP indices
%type <ParamList> ParamList // For call param lists & GEP indices
%type <ValueList> IndexList // For GEP indices
%type <TypeList> TypeListI
%type <TypeWithAttrsList> ArgTypeList ArgTypeListI
@ -2609,7 +2609,7 @@ BBTerminatorInst : RET ResolvedVal { // Return with a result...
$$ = S;
CHECK_FOR_ERROR
}
| INVOKE OptCallingConv ResultTypes ValueRef '(' ValueRefList ')' OptFuncAttrs
| INVOKE OptCallingConv ResultTypes ValueRef '(' ParamList ')' OptFuncAttrs
TO LABEL ValueRef UNWIND LABEL ValueRef {
// Handle the short syntax
@ -2624,7 +2624,7 @@ BBTerminatorInst : RET ResolvedVal { // Return with a result...
ParamAttrsWithIndex PAWI; PAWI.index = 0; PAWI.attrs = $8;
Attrs.push_back(PAWI);
}
ValueRefList::iterator I = $6->begin(), E = $6->end();
ParamList::iterator I = $6->begin(), E = $6->end();
unsigned index = 1;
for (; I != E; ++I, ++index) {
const Type *Ty = I->Val->getType();
@ -2665,7 +2665,7 @@ BBTerminatorInst : RET ResolvedVal { // Return with a result...
// correctly!
FunctionType::param_iterator I = Ty->param_begin();
FunctionType::param_iterator E = Ty->param_end();
ValueRefList::iterator ArgI = $6->begin(), ArgE = $6->end();
ParamList::iterator ArgI = $6->begin(), ArgE = $6->end();
for (; ArgI != ArgE && I != E; ++ArgI, ++I) {
if (ArgI->Val->getType() != *I)
@ -2755,25 +2755,37 @@ PHIList : Types '[' ValueRef ',' ValueRef ']' { // Used for PHI nodes
};
ValueRefList : Types ValueRef OptParamAttrs {
ParamList : Types ValueRef OptParamAttrs {
if (!UpRefs.empty())
GEN_ERROR("Invalid upreference in type: " + (*$1)->getDescription());
// Used for call and invoke instructions
$$ = new ValueRefList();
ValueRefListEntry E; E.Attrs = $3; E.Val = getVal($1->get(), $2);
$$ = new ParamList();
ParamListEntry E; E.Attrs = $3; E.Val = getVal($1->get(), $2);
$$->push_back(E);
delete $1;
}
| ValueRefList ',' Types ValueRef OptParamAttrs {
| LABEL ValueRef OptParamAttrs {
// Labels are only valid in ASMs
$$ = new ParamList();
ParamListEntry E; E.Attrs = $3; E.Val = getBBVal($2);
$$->push_back(E);
}
| ParamList ',' Types ValueRef OptParamAttrs {
if (!UpRefs.empty())
GEN_ERROR("Invalid upreference in type: " + (*$3)->getDescription());
$$ = $1;
ValueRefListEntry E; E.Attrs = $5; E.Val = getVal($3->get(), $4);
ParamListEntry E; E.Attrs = $5; E.Val = getVal($3->get(), $4);
$$->push_back(E);
delete $3;
CHECK_FOR_ERROR
}
| /*empty*/ { $$ = new ValueRefList(); };
| ParamList ',' LABEL ValueRef OptParamAttrs {
$$ = $1;
ParamListEntry E; E.Attrs = $5; E.Val = getBBVal($4);
$$->push_back(E);
CHECK_FOR_ERROR
}
| /*empty*/ { $$ = new ParamList(); };
IndexList // Used for gep instructions and constant expressions
: /*empty*/ { $$ = new std::vector<Value*>(); }
@ -2919,7 +2931,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
delete $2; // Free the list...
CHECK_FOR_ERROR
}
| OptTailCall OptCallingConv ResultTypes ValueRef '(' ValueRefList ')'
| OptTailCall OptCallingConv ResultTypes ValueRef '(' ParamList ')'
OptFuncAttrs {
// Handle the short syntax
@ -2935,7 +2947,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
Attrs.push_back(PAWI);
}
unsigned index = 1;
ValueRefList::iterator I = $6->begin(), E = $6->end();
ParamList::iterator I = $6->begin(), E = $6->end();
for (; I != E; ++I, ++index) {
const Type *Ty = I->Val->getType();
if (Ty == Type::VoidTy)
@ -2980,7 +2992,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
//
FunctionType::param_iterator I = Ty->param_begin();
FunctionType::param_iterator E = Ty->param_end();
ValueRefList::iterator ArgI = $6->begin(), ArgE = $6->end();
ParamList::iterator ArgI = $6->begin(), ArgE = $6->end();
for (; ArgI != ArgE && I != E; ++ArgI, ++I) {
if (ArgI->Val->getType() != *I)

View File

@ -981,7 +981,7 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
llvm::ArgListType *ArgList;
llvm::TypeWithAttrs TypeWithAttrs;
llvm::TypeWithAttrsList *TypeWithAttrsList;
llvm::ValueRefList *ValueRefList;
llvm::ParamList *ParamList;
// Represent the RHS of PHI node
std::list<std::pair<llvm::Value*,
@ -1021,7 +1021,7 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
%type <ConstVector> ConstVector
%type <ArgList> ArgList ArgListH
%type <PHIList> PHIList
%type <ValueRefList> ValueRefList // For call param lists & GEP indices
%type <ParamList> ParamList // For call param lists & GEP indices
%type <ValueList> IndexList // For GEP indices
%type <TypeList> TypeListI
%type <TypeWithAttrsList> ArgTypeList ArgTypeListI
@ -2609,7 +2609,7 @@ BBTerminatorInst : RET ResolvedVal { // Return with a result...
$$ = S;
CHECK_FOR_ERROR
}
| INVOKE OptCallingConv ResultTypes ValueRef '(' ValueRefList ')' OptFuncAttrs
| INVOKE OptCallingConv ResultTypes ValueRef '(' ParamList ')' OptFuncAttrs
TO LABEL ValueRef UNWIND LABEL ValueRef {
// Handle the short syntax
@ -2624,7 +2624,7 @@ BBTerminatorInst : RET ResolvedVal { // Return with a result...
ParamAttrsWithIndex PAWI; PAWI.index = 0; PAWI.attrs = $8;
Attrs.push_back(PAWI);
}
ValueRefList::iterator I = $6->begin(), E = $6->end();
ParamList::iterator I = $6->begin(), E = $6->end();
unsigned index = 1;
for (; I != E; ++I, ++index) {
const Type *Ty = I->Val->getType();
@ -2665,7 +2665,7 @@ BBTerminatorInst : RET ResolvedVal { // Return with a result...
// correctly!
FunctionType::param_iterator I = Ty->param_begin();
FunctionType::param_iterator E = Ty->param_end();
ValueRefList::iterator ArgI = $6->begin(), ArgE = $6->end();
ParamList::iterator ArgI = $6->begin(), ArgE = $6->end();
for (; ArgI != ArgE && I != E; ++ArgI, ++I) {
if (ArgI->Val->getType() != *I)
@ -2755,25 +2755,37 @@ PHIList : Types '[' ValueRef ',' ValueRef ']' { // Used for PHI nodes
};
ValueRefList : Types ValueRef OptParamAttrs {
ParamList : Types ValueRef OptParamAttrs {
if (!UpRefs.empty())
GEN_ERROR("Invalid upreference in type: " + (*$1)->getDescription());
// Used for call and invoke instructions
$$ = new ValueRefList();
ValueRefListEntry E; E.Attrs = $3; E.Val = getVal($1->get(), $2);
$$ = new ParamList();
ParamListEntry E; E.Attrs = $3; E.Val = getVal($1->get(), $2);
$$->push_back(E);
delete $1;
}
| ValueRefList ',' Types ValueRef OptParamAttrs {
| LABEL ValueRef OptParamAttrs {
// Labels are only valid in ASMs
$$ = new ParamList();
ParamListEntry E; E.Attrs = $3; E.Val = getBBVal($2);
$$->push_back(E);
}
| ParamList ',' Types ValueRef OptParamAttrs {
if (!UpRefs.empty())
GEN_ERROR("Invalid upreference in type: " + (*$3)->getDescription());
$$ = $1;
ValueRefListEntry E; E.Attrs = $5; E.Val = getVal($3->get(), $4);
ParamListEntry E; E.Attrs = $5; E.Val = getVal($3->get(), $4);
$$->push_back(E);
delete $3;
CHECK_FOR_ERROR
}
| /*empty*/ { $$ = new ValueRefList(); };
| ParamList ',' LABEL ValueRef OptParamAttrs {
$$ = $1;
ParamListEntry E; E.Attrs = $5; E.Val = getBBVal($4);
$$->push_back(E);
CHECK_FOR_ERROR
}
| /*empty*/ { $$ = new ParamList(); };
IndexList // Used for gep instructions and constant expressions
: /*empty*/ { $$ = new std::vector<Value*>(); }
@ -2919,7 +2931,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
delete $2; // Free the list...
CHECK_FOR_ERROR
}
| OptTailCall OptCallingConv ResultTypes ValueRef '(' ValueRefList ')'
| OptTailCall OptCallingConv ResultTypes ValueRef '(' ParamList ')'
OptFuncAttrs {
// Handle the short syntax
@ -2935,7 +2947,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
Attrs.push_back(PAWI);
}
unsigned index = 1;
ValueRefList::iterator I = $6->begin(), E = $6->end();
ParamList::iterator I = $6->begin(), E = $6->end();
for (; I != E; ++I, ++index) {
const Type *Ty = I->Val->getType();
if (Ty == Type::VoidTy)
@ -2980,7 +2992,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
//
FunctionType::param_iterator I = Ty->param_begin();
FunctionType::param_iterator E = Ty->param_end();
ValueRefList::iterator ArgI = $6->begin(), ArgE = $6->end();
ParamList::iterator ArgI = $6->begin(), ArgE = $6->end();
for (; ArgI != ArgE && I != E; ++ArgI, ++I) {
if (ArgI->Val->getType() != *I)

View File

@ -1506,7 +1506,10 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
SmallVector<Value*, 16> Args;
// Read the fixed params.
for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i, ++OpNum) {
Args.push_back(getFnValueByID(Record[OpNum], FTy->getParamType(i)));
if (FTy->getParamType(i)->getTypeID()==Type::LabelTyID)
Args.push_back(getBasicBlock(Record[OpNum]));
else
Args.push_back(getFnValueByID(Record[OpNum], FTy->getParamType(i)));
if (Args.back() == 0) return Error("Invalid CALL record");
}

View File

@ -1188,13 +1188,18 @@ void AsmPrinter::printInlineAsm(const MachineInstr *MI) const {
unsigned OpFlags = MI->getOperand(OpNo).getImmedValue();
++OpNo; // Skip over the ID number.
AsmPrinter *AP = const_cast<AsmPrinter*>(this);
if ((OpFlags & 7) == 4 /*ADDR MODE*/) {
Error = AP->PrintAsmMemoryOperand(MI, OpNo, AsmPrinterVariant,
Modifier[0] ? Modifier : 0);
} else {
Error = AP->PrintAsmOperand(MI, OpNo, AsmPrinterVariant,
Modifier[0] ? Modifier : 0);
if (Modifier[0]=='l') // labels are target independent
printBasicBlockLabel(MI->getOperand(OpNo).getMachineBasicBlock(),
false, false);
else {
AsmPrinter *AP = const_cast<AsmPrinter*>(this);
if ((OpFlags & 7) == 4 /*ADDR MODE*/) {
Error = AP->PrintAsmMemoryOperand(MI, OpNo, AsmPrinterVariant,
Modifier[0] ? Modifier : 0);
} else {
Error = AP->PrintAsmOperand(MI, OpNo, AsmPrinterVariant,
Modifier[0] ? Modifier : 0);
}
}
}
if (Error) {

View File

@ -803,10 +803,13 @@ void ScheduleDAG::EmitNode(SDNode *Node, unsigned InstanceNo,
if (ConstantSDNode *CS =
dyn_cast<ConstantSDNode>(Node->getOperand(i))) {
MI->addImmOperand(CS->getValue());
} else {
GlobalAddressSDNode *GA =
cast<GlobalAddressSDNode>(Node->getOperand(i));
} else if (GlobalAddressSDNode *GA =
dyn_cast<GlobalAddressSDNode>(Node->getOperand(i))) {
MI->addGlobalAddressOperand(GA->getGlobal(), GA->getOffset());
} else {
BasicBlockSDNode *BB =
cast<BasicBlockSDNode>(Node->getOperand(i));
MI->addMachineBasicBlockOperand(BB->getBasicBlock());
}
}
break;

View File

@ -3489,31 +3489,37 @@ void SelectionDAGLowering::visitInlineAsm(CallInst &I) {
}
// If this is an input or an indirect output, process the call argument.
// BasicBlocks are labels, currently appearing only in asm's.
if (OpInfo.CallOperandVal) {
OpInfo.CallOperand = getValue(OpInfo.CallOperandVal);
const Type *OpTy = OpInfo.CallOperandVal->getType();
// If this is an indirect operand, the operand is a pointer to the
// accessed type.
if (OpInfo.isIndirect)
OpTy = cast<PointerType>(OpTy)->getElementType();
// If OpTy is not a first-class value, it may be a struct/union that we
// can tile with integers.
if (!OpTy->isFirstClassType() && OpTy->isSized()) {
unsigned BitSize = TD->getTypeSizeInBits(OpTy);
switch (BitSize) {
default: break;
case 1:
case 8:
case 16:
case 32:
case 64:
OpTy = IntegerType::get(BitSize);
break;
if (isa<BasicBlock>(OpInfo.CallOperandVal))
OpInfo.CallOperand =
DAG.getBasicBlock(FuncInfo.MBBMap[cast<BasicBlock>(OpInfo.CallOperandVal)]);
else {
OpInfo.CallOperand = getValue(OpInfo.CallOperandVal);
const Type *OpTy = OpInfo.CallOperandVal->getType();
// If this is an indirect operand, the operand is a pointer to the
// accessed type.
if (OpInfo.isIndirect)
OpTy = cast<PointerType>(OpTy)->getElementType();
// If OpTy is not a first-class value, it may be a struct/union that we
// can tile with integers.
if (!OpTy->isFirstClassType() && OpTy->isSized()) {
unsigned BitSize = TD->getTypeSizeInBits(OpTy);
switch (BitSize) {
default: break;
case 1:
case 8:
case 16:
case 32:
case 64:
OpTy = IntegerType::get(BitSize);
break;
}
}
OpVT = TLI.getValueType(OpTy, true);
}
OpVT = TLI.getValueType(OpTy, true);
}
OpInfo.ConstraintVT = OpVT;

View File

@ -1396,10 +1396,15 @@ void TargetLowering::LowerAsmOperandForConstraint(SDOperand Op,
SelectionDAG &DAG) {
switch (ConstraintLetter) {
default: break;
case 'X': // Allows any operand; labels (basic block) use this.
if (Op.getOpcode() == ISD::BasicBlock) {
Ops.push_back(Op);
return;
}
// fall through
case 'i': // Simple Integer or Relocatable Constant
case 'n': // Simple Integer
case 's': // Relocatable Constant
case 'X': { // Allows any operand.
case 's': { // Relocatable Constant
// These operands are interested in values of the form (GV+C), where C may
// be folded in as an offset of GV, or it may be explicitly added. Also, it
// is possible and fine if either GV or C are missing.

View File

@ -0,0 +1,41 @@
; RUN: llvm-as < %s | opt -std-compile-opts | llc
; ModuleID = 'block12.c'
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
target triple = "i686-apple-darwin8"
define void @bar() {
entry:
br label %"LASM$foo"
"LASM$foo": ; preds = %entry
call void asm sideeffect ".file \22block12.c\22", "~{dirflag},~{fpsr},~{flags}"( )
call void asm sideeffect ".line 1", "~{dirflag},~{fpsr},~{flags}"( )
call void asm sideeffect "int $$1", "~{dirflag},~{fpsr},~{flags},~{memory}"( )
call void asm sideeffect ".file \22block12.c\22", "~{dirflag},~{fpsr},~{flags}"( )
call void asm sideeffect ".line 2", "~{dirflag},~{fpsr},~{flags}"( )
call void asm sideeffect "brl ${0:l}", "X,~{dirflag},~{fpsr},~{flags},~{memory}"( label %"LASM$foo" )
br label %return
return: ; preds = %"LASM$foo"
ret void
}
define void @baz() {
entry:
call void asm sideeffect ".file \22block12.c\22", "~{dirflag},~{fpsr},~{flags}"( )
call void asm sideeffect ".line 3", "~{dirflag},~{fpsr},~{flags}"( )
call void asm sideeffect "brl ${0:l}", "X,~{dirflag},~{fpsr},~{flags},~{memory}"( label %"LASM$foo" )
call void asm sideeffect ".file \22block12.c\22", "~{dirflag},~{fpsr},~{flags}"( )
call void asm sideeffect ".line 4", "~{dirflag},~{fpsr},~{flags}"( )
call void asm sideeffect "int $$1", "~{dirflag},~{fpsr},~{flags},~{memory}"( )
br label %"LASM$foo"
"LASM$foo": ; preds = %entry
call void asm sideeffect ".file \22block12.c\22", "~{dirflag},~{fpsr},~{flags}"( )
call void asm sideeffect ".line 5", "~{dirflag},~{fpsr},~{flags}"( )
call void asm sideeffect "int $$1", "~{dirflag},~{fpsr},~{flags},~{memory}"( )
br label %return
return: ; preds = %"LASM$foo"
ret void
}